我有以下结构:
public class Object1{
private HashMap<Double, Node> myMap;
...
public void cancelItem(Item o) {
for(Map.Entry<Double, Node> nn: myMap.entrySet()) {
if(nn.getValue().containItem(o)) {
nn.getValue().cancelItemFromNode(o);
}
}
}
}
和另一个班级
public class Node{
private HashMap<String,Item> itemIDHashMap;
public boolean containItemID(Item o) {
return itemIDHashMap.containsKey(o.getItemID());
}
public void cancelItemFromNode(Item o) {
if(itemIDHashMap.containsKey(o.getItemID())) {
itemIDHashMap.remove(o.getItemID());
}
}
}
因此上面的代码执行此操作:每当调用Object1
的{{1}}方法时,它会迭代cancelItem
散列映射以查找myMap
,其中包含另一个散列映射{ {1}},并检查Node
是否包含相同的商品ID,如果是,则从itemIDHashMap
中删除该商品。
现在,根据我的理解,因为我在不使用迭代器的情况下迭代hashmap itemIDHashMap
而我正在尝试从hashmap中删除元素,为什么它不会在运行时抛出itemIDHashMap
?
更新
道歉。我忘了澄清。我知道我实际上迭代一个散列图,但从另一个散列图中删除键值对。但是,在我上面的设计中,我相信我仍然在修改myMap
的内容,它仍然是ConcurrentModificationException
哈希映射的一部分,因为我从哈希映射中移除Node
键值对myMap
课程。
从技术上讲,我仍然在修改Item
hashmap的内容?
答案 0 :(得分:7)
您正在迭代一个Map
- myMap
的条目集,但会从不同的Map
s - itemIDHashMap
中删除条目。因此,没有理由抛出ConcurrentModificationException
。
从itemIDHashMap
的{{1}}实例变量中删除条目,这是您正在迭代的Node
的值,使无结构更改 Map
,因此被允许。
以下是Map
Javadoc中的一些相关引用,它解释了在迭代HashMap
的条目时抛出ConcurrentModificationException
的时间:
结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已包含的键关联的值不是结构修改。
...
此类的所有“集合视图方法”返回的迭代器都是快速失败的:如果在创建迭代器之后的任何时候对映射进行结构修改,除非通过迭代器自己的remove方法,迭代器将抛出ConcurrentModificationException 。因此,在并发修改的情况下,迭代器快速而干净地失败,而不是在未来的未确定时间冒着任意的,非确定性行为的风险。
Map
是上面提到的“集合视图方法”之一。