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

时间:2018-04-22 05:31:59

标签: 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);
                }
            }
     }
}

和另一个班级

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的内容?

1 个答案:

答案 0 :(得分:7)

您正在迭代一个Map - myMap的条目集,但会从不同的Map s - itemIDHashMap中删除条目。因此,没有理由抛出ConcurrentModificationException

itemIDHashMap的{​​{1}}实例变量中删除条目,这是您正在迭代的Node的值,使无结构更改 Map,因此被允许。

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

  

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

     

...

     

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

Map是上面提到的“集合视图方法”之一。