Java:为什么以下构造没有抛出ConcurrentModificationException?

use*_*197 2 java

我有以下结构:

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);
                }
            }
     }
}
Run Code Online (Sandbox Code Playgroud)

和另一堂课

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());
        } 
    }
}
Run Code Online (Sandbox Code Playgroud)

所以,上面的代码做到这一点:无论何时Object1cancelItem方法被调用时,它遍历的myMapHashMap来找到一个Node,它包含了另一个HashMap中itemIDHashMap,并检查是否itemIDHashMap包含相同的项目ID,如果确实如此,那么从删除的项itemIDHashMap.

现在,从我的理解,因为我在myMap不使用迭代器的情况下迭代hashmap 而我试图从hashmap中删除元素,为什么它不会ConcurrentModificationException在运行时抛出?

更新: 道歉.我忘了澄清.我知道我实际上迭代一个散列图,但从另一个散列图中删除键值对.但是,在我上面的设计中,我相信我仍在修改内容Node,它仍然是myMaphashmap的一部分,因为我ItemNode类的hashmap中删除了键值对.从技术上讲,我还在修改myMaphashmap 的内容?

Era*_*ran 7

您正在迭代一个条目集Map- myMap- 但是从不同的Maps - 中删除条目itemIDHashMap.因此没有理由ConcurrentModificationException被抛出.

从a的itemIDHashMap实例变量中删除条目Node,这是Map您正在迭代的值,不会对其进行任何结构更改,Map因此是允许的.

以下是来自HashMapJavadoc的一些相关引用,它解释了在ConcurrentModificationException迭代以下条目时抛出的时间Map:

结构修改是添加或删除一个或多个映射的任何操作; 仅更改与实例已包含的键关联的值不是结构修改.

...

所有这个类的"集合视图方法"返回的迭代器都是快速失败的:如果在创建迭代器之后的任何时候对映射进行结构修改,除了通过迭代器自己的remove方法之外,迭代器将抛出ConcurrentModificationException..因此,在并发修改的情况下,迭代器快速而干净地失败,而不是在未来的未确定时间冒任意,非确定性行为的风险.

entrySet() 是上面提到的"集合视图方法"之一.