我有以下代码,我希望案例2场景抛出ConcurrentModificationException
,但它运行成功。据我所知,如果我在地图中使用单个键执行相同操作,则不会抛出异常,因为here
但是当我再现这个具有两个案例的多个键的情景时再次 -
案例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
。为什么??
答案 0 :(得分:4)
在第一种情况下,您修改地图的结构,以便获得CME(添加新的键/值对)。在第二种情况下,您不会修改结构(覆盖现有键的值)。所以你不会得到CME
答案 1 :(得分:1)
当它的结构在迭代时被改变时抛出ConcurrentModificationException但在第二种情况下结构没有变化。这意味着地图中的现有密钥只有更新(第二种情况下不会添加或删除会导致结构发生变化)
答案 2 :(得分:1)
您可以参考to the javadoc:
迭代器[...]快速失败:如果地图在创建迭代器后的任何时间 结构修改 ,除了通过迭代器自己的remove方法,迭代器将抛出
ConcurrentModificationException
。
结构修改的定义也可以在那里找到:
结构修改是添加或删除一个或多个映射的任何操作; 仅仅更改与实例已包含的键关联的值不是结构修改
最后,还值得阅读最后一段:
失败的迭代器尽最大努力抛出
ConcurrentModificationException
。因此,编写依赖于此异常的程序以确保其正确性是错误的:迭代器的快速失败行为应仅用于检测错误。