【问题标题】:Clarification @ConcurrentModificationException in HashMapHashMap 中的说明 @ConcurrentModificationException
【发布时间】:2014-03-06 11:50:34
【问题描述】:

我期待下面的代码中出现ConcurrentModificationException,但它工作正常。

HashMap<Integer, String>table1 = new HashMap<Integer, String>();
    table1.put(1, "Sam");
    table1.put(2, "Jon");
    table1.put(3, "Doe");

    Iterator itr1 = table1.entrySet().iterator();

    table1.put(3, "DONN");
    while(itr1.hasNext())
    {
        System.out.println("---Value--" + itr1.next());
    }

根据HashMap 的 JavaDoc:

这个类的所有“集合视图方法”返回的迭代器都是快速失败的:如果在迭代器创建后的任何时候对映射进行结构修改,除了通过迭代器自己的 remove 方法之外,迭代器将抛出 ConcurrentModificationException。

因此,由于我在获得Iterator 后修改了HashMap,所以我应该获得ConcurrentModificationException。为什么不扔?

【问题讨论】:

  • 该文档还指出:“快速失败的迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写一个依赖于该异常的正确性的程序是错误的:迭代器的快速失败行为应仅用于检测错误。"

标签: java iterator hashmap


【解决方案1】:

HashMap的当前实现中,为现有键添加条目不被视为结构修改,并且永远不会触发ConcurrentModificationException。尝试使用新键,例如table1.put(4, "UPS"); 获取ConcurrentModificationException

【讨论】:

    【解决方案2】:

    您正在修改HashMap,而不是您在其上获取的entrySet,在这里您正在通过entrySet 获取iterator

    按照entrySet方法javaDoc:

    如果在对集合进行迭代时修改了映射(通过迭代器自己的删除操作或通过对迭代器返回的映射条目的 setValue 操作除外),则迭代的结果是不确定的。

    所以你没有收到ConcurrentModificationException

    这里是entrySet的完整解释:

    返回此映射中包含的映射的 Set 视图。集合由地图支持,因此对地图的更改会反映在集合中,反之亦然。如果在对集合进行迭代时修改了映射(通过迭代器自己的删除操作或通过迭代器返回的映射条目上的 setValue 操作除外),则迭代的结果是未定义的。该集合支持元素移除,即通过 Iterator.remove、Set.remove、removeAll、retainAll 和 clear 操作从映射中移除相应的映射。它不支持 add 或 addAll 操作。

    【讨论】:

    • “未定义”不排除抛出 ConcurrentModificationException 并且在当前实现中它确实抛出 ConcurrentModificationException,但前提是添加或删除键。
    • 是的,知道了,因为他使用的是同一个密钥,HashMap 没有被修改。
    【解决方案3】:

    尝试table1.put(4, "DONN"),迭代器将因 ConcurrentModificationException 而失败。 table1.put(3, "DONN") 不会改变映射结构,只是替换 key=3 的值,因为它已经存在

    【讨论】:

      猜你喜欢
      • 2015-09-23
      • 2023-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-25
      • 2013-08-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多