2014-03-06 126 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的值,因爲它已經存在