在Map中,如果我们使用现有密钥进行修改,我们就不会收到ConcurrentModificationException

时间:2015-06-08 05:28:49

标签: java multithreading concurrency

我有以下代码,我希望案例2场景抛出ConcurrentModificationException,但它运行成功。据我所知,如果我在地图中使用单个键执行相同操作,则不会抛出异常,因为here 但是当我再现这个具有两个案例的多个键的情景时再次 -

  1. 用新密钥修改。
  2. 通过现有密钥修改。
  3. 案例1:

        Map<String,String> mp = new HashMap<String,String>();
        mp.put("1", "10");
        mp.put("2", "11");
        mp.put("3", "12");
        mp.put("4", "13");
    
        for (String key :mp.keySet()) {
            mp.put("5", "14");
        }
    

    这将按预期工作,抛出ConcurrentModificationException

    案例2:

        Map<String,String> mp = new HashMap<String,String>();
        mp.put("1", "10");
        mp.put("2", "11");
        mp.put("3", "12");
        mp.put("4", "13");
    
        for (String key :mp.keySet()) {
            mp.put(key, "14");
        }
    

    它不会抛出ConcurrentModificationException。为什么??

3 个答案:

答案 0 :(得分:4)

在第一种情况下,您修改地图的结构,以便获得CME(添加新的键/值对)。在第二种情况下,您不会修改结构(覆盖现有键的值)。所以你不会得到CME

答案 1 :(得分:1)

当它的结构在迭代时被改变时抛出ConcurrentModificationException但在第二种情况下结构没有变化。这意味着地图中的现有密钥只有更新(第二种情况下不会添加或删除会导致结构发生变化)

请参阅http://javahungry.blogspot.com/2014/04/fail-fast-iterator-vs-fail-safe-iterator-difference-with-example-in-java.html

答案 2 :(得分:1)

您可以参考to the javadoc

  

迭代器[...]快速失败:如果地图在创建迭代器后的任何时间 结构修改 ,除了通过迭代器自己的remove方法,迭代器将抛出ConcurrentModificationException

结构修改的定义也可以在那里找到:

  

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

最后,还值得阅读最后一段:

  

失败的迭代器尽最大努力抛出ConcurrentModificationException 。因此,编写依赖于此异常的程序以确保其正确性是错误的:迭代器的快速失败行为应仅用于检测错误。

相关问题