【问题标题】:ConcurrentModificationException not occour when adding dublicate element添加重复元素时不会发生 ConcurrentModificationException
【发布时间】:2019-02-06 19:06:57
【问题描述】:

我们在遍历list的时候添加重复元素,iterator没有给出并发修改异常,这是什么原因?

Map<String,String> myMap = new HashMap<String,String>();
    myMap.put("1", "1");
    myMap.put("2", "2");
    myMap.put("3", "3");
    Iterator<String> it1 = myMap.keySet().iterator();
    while(it1.hasNext()){
        String key = (String) it1.next();
        System.out.println("Map Value:"+myMap.get(key));
        if(key.equals("2")){
            myMap.put("1","4");
        }
    }

【问题讨论】:

  • 阅读文档,即HashMap的javadoc:"请注意,一般来说,不能保证迭代器的快速失败行为, 在存在不同步的并发修改的情况下无法做出任何硬性保证。快速失败的迭代器会尽最大努力抛出ConcurrentModificationException。因此,编写依赖于此异常的正确性的程序是错误的:迭代器的快速失败行为应该只用于检测错误。”

标签: java collections hashmap


【解决方案1】:

由于您正在更新 myMap 中的现有键值,因此它的大小没有更改,并且您没有收到 ConcurrentModificationException。

如果您想知道 Iterator 如何检查修改,它的实现存在于 AbstractList 类中,其中定义了一个 int 变量 modCount。 modCount 提供列表大小已更改的次数。在每个 next() 调用中使用 modCount 值来检查函数 checkForComodification() 中的任何修改。

【讨论】:

    【解决方案2】:

    您覆盖了映射的一个条目,因此迭代器在除此之外工作,因为iterator() 检查涉及映射的结构修改。
    添加一个新条目,它会抛出异常myMap.put("4","4");
    请注意,实际上您注意到的行为是一个实现细节,即使它有效,您也不应该将其视为有效代码。
    为了符合 Map API 规范,您不必更改使用迭代器时引用的对象的地图。

    Map.keySet() 确实指定了:

    如果在对集合进行迭代时修改了地图 (通过迭代器自己的删除操作除外),结果 迭代未定义

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-18
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      • 2019-06-24
      • 1970-01-01
      • 2021-12-02
      • 1970-01-01
      相关资源
      最近更新 更多