[英]Good practice to avoid ConcurrentModification of static collection
考慮玩家等級...當玩家加入游戲(創建對象)時,它會檢查已經加入的同名玩家...
public class Player {
private static List<Player> players = new ArrayList<>();
private String name;
public Player(String name) {
this.name = name;
for (Player otherPlayer : players) { // Iterating static field
if (otherPlayer.name.equalsIgnoreCase(name)) {
otherPlayer.quit("Somebody with the same name joined the game");
}
}
}
public void quit(String message) {
players.remove(this); // Modifying static field
Server.disconnect(this, message);
}
}
我知道Iterator可以處理這個問題,但我們並不總是知道外部方法中的公共靜態字段會發生什么,以及何時使用foreach以及何時使用Iterator ...
這個問題有什么好的做法嗎?
第一個也是更重要的良好做法稱為關注點分離 。 如下所示:Player類應該為單個玩家建模。
您正在混合作為播放器的責任並在一個地方管理整個Player對象集。 不要那樣做!
這兩件事根本就不屬於一體。 在這個意義上:應該有一個PlayerManager
例如類, 知道所有玩家。 而且忘了使用像這樣的static
字段。 因為這會在班級的不同方面之間產生超緊密耦合。 例如,當您需要多個玩家列表時會發生什么? 如果您有這么多玩家想要根據某些屬性在桶中組織它們怎么辦?
除此之外,直接的答案是:而不是立即從列表中刪除對象 - 將它們收集到第二個playersToBeDeleted
列表中。 在迭代第一個列表之后,只需使用players.removeAll(playersToBeDeleted)
。
並談論好的做法:仔細考慮你是否真的想要使用列表 - 或者如果Set不是更好的選擇。 列表總是暗示訂單,而且,它們允許重復添加相同的對象。 而Set則免費為您提供“獨特元素”語義!
我看到你正在嘗試調用list.remove(entry)
方法,同時仍在for-each塊中。 不要那樣做。
當需要時,使用Iterator
而不是for-each構造:
請注意, Iterator.remove
是在迭代期間修改集合的唯一安全方法; 如果在迭代進行過程中以任何其他方式修改基礎集合,則行為未指定。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.