2014-03-06 77 views
3

我期待ConcurrentModificationException在下面的代码,但它工作正常。澄清@ConcurrentModificationException在HashMap

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()); 
    } 

按该JavaDoc中HashMap

所有的此类的“collection视图方法”所返回的迭代器都是快速失败的:如果地图随时迭代后结构修饰以任何方式创建,除了通过迭代器自己的remove方法外,迭代器将抛出ConcurrentModificationException异常。

如此以来,我收到Iterator我应该得到的ConcurrentModificationException后修改HashMap。为什么不投掷?

+1

该文档还指出:“失效快速迭代器尽最大努力抛出ConcurrentModificationException。因此,编写依赖于此异常的程序的正确性会导致错误:*迭代器的失效 - 快速行为应该仅用于检测错误*。“ – kiheru

回答

4

把一个现有键的条目不被视为一个结构修饰在目前执行的HashMap,永远不会触发ConcurrentModificationException。尝试用一个新的密钥,例如table1.put(4, "UPS");得到ConcurrentModificationException

+0

谢谢@Holger ....你正确:) – Skabdus

2

您正在修改您获得它的HashMap不是的entrySet,在这里你都获得iteratorentrySet

按照

entrySet方法的Javadoc:

如果图在对集合进行迭代的过程中进行修改(除了通过迭代器自己的删除操作,或者通过迭代器返回的映射条目上的setValue操作),迭代的结果是未定义的。

所以你没有得到ConcurrentModificationException

这里的entrySet是的完整的解释:

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

+0

“未定义”不排除抛出ConcurrentModificationException,并且在当前的实现中它不会抛出ConcurrentModificationException,但只有在添加或删除键时才会抛出ConcurrentModificationException。 – Holger

+2

是的,得到它,因为他使用相同的键,'HashMap'没有得到修改。 – Zeeshan

2

尝试table1.put(4, "DONN")迭代器将失败并出现ConcurrentModificationException。 table1.put(3, "DONN")不改变地图的结构,但只是取代了关键= 3的值,因为它已经存在