目前我的代码导致间歇性的ConcurrentModificationException错误,可能是因为我循环遍历HashMap的方式:
for (Map.Entry<String, Entity> entry : entities.entrySet()) {
String key = entry.getKey();
Entity item = entry.getValue();
if (item.isDestroyed()){
entities.remove(key);
ViewManager.getInstance().removeItem(key);
//INSTRUCT THE ENTITY TO PERFORM IT'S DESTROYED BEHAVIOR item.Destroyed()
} else {
item.update(1);
ConsoleItem ci = new ConsoleItemImpl(item.getIdentifier(), item.getLocation(), ColorStringConverter.getInstance().StringToColor(item.getSide()), item.getAngle(), item.getShape(), item.toString(), item.isDestroyed(), item.isDamaged());
ViewManager.getInstance().updateItem(ci);
}
item.update(1);
}
// updateInfo call
ViewManager.getInstance().updateInfo(summary());
}
如何通过HashMap连续循环并避免出现ConcurrentModificationException错误?
答案 0 :(得分:5)
循环播放时无法修改地图。您必须制作地图副本,使用ConcurrentHashMap或使用iterator。如果它在多线程环境中,那么您可以在同步块中进行修改。
另一种选择是使用iterator。
我用下面的迭代器重写了for for循环:
for(Iterator<Map.Entry<String, Entity>> iterator = entities.entrySet().iterator(); iterator.hasNext(); ){
Map.Entry<String, Entity> entry = iterator.next();
String key = entry.getKey();
Entity item = entry.getValue();
if (item.isDestroyed()){
//Notice using an iterator to remove
iterator.remove();
ViewManager.getInstance().removeItem(key);
//INSTRUCT THE ENTITY TO PERFORM IT'S DESTROYED BEHAVIOR item.Destroyed()
} else {
item.update(1);
ConsoleItem ci = new ConsoleItemImpl(item.getIdentifier(), item.getLocation(), ColorStringConverter.getInstance().StringToColor(item.getSide()), item.getAngle(), item.getShape(), item.toString(), item.isDestroyed(), item.isDamaged());
ViewManager.getInstance().updateItem(ci);
}
item.update(1);
}
我不确定连续循环HashMap的那部分。哈希映射具有一组有限的键,因此您通常会遍历键集。如果由于某种原因想要连续循环,那么你需要首先告诉我们背后的原因以及连续循环的终端条件(它真的不能永远,可以吗?)。
答案 1 :(得分:3)
正如其他答案中所述,使用基于for循环的Iterator而不是for-each循环是避免ConcurrentModificationExemptions的最佳选择。至于无限循环,请查看Guava的Iterators静态实用程序类中的cycle method。它需要一个Iterable(例如HashMap)并返回一个迭代循环遍历数据的Iterator,直到Iterable为空或者你打破了循环。
答案 2 :(得分:1)
如何使用迭代器和while循环?
Iterator<String> iterator = map.iterator();
String key;
String value;
while (iterator.hasNext()) {
key = iterator.next();
value = map.get(key);
}
答案 3 :(得分:1)
循环时不能调用remote(key)方法,但可以通过迭代器删除条目:
Map<String, String> map = new HashMap<String, String>();
map.put("one", "1");
map.put("two", "2");
map.put("three", "3");
for (Iterator<Map.Entry<String, String>> i = map.entrySet().iterator(); i.hasNext();)
{
Map.Entry<String, String> curEntry = i.next();
if (curEntry.getKey().equals("two"))
i.remove();
}
答案 4 :(得分:0)
假设您仅在线程上访问地图,请使用迭代器,正如其他人所建议的那样。
我在考虑迭代hashmap时的性能, 所以我对10 ^ 6个随机Longs进行了25次迭代的快速测试,然后删除了10%, 使用不同的地图实现:ConcurrentHashMap,HashMap,LinkedHashMap 和一个TreeMap。
链接的hashmap应该是为迭代而定制的,它似乎是最有效的。我认为峰值是由于gc。
......但差异小于我的预期。