關於Map表循環過程刪除操作出現的java.util.ConcurrentModificationException 異常

當使用 fail-fast iterator 對 Collection 或 Map 進行迭代操作過程中嘗試直接修改 Collection / Map 的內容時,即使是在單線程下運行,   java .util .ConcurrentModificationException 異常也將被拋出。

  Iterator 是工作在一個獨立的線程中,並且擁有一個 mutex 鎖。 Iterator 被創建之後會建立一個指向原來對象的單鏈索引表,當原來的對象數量發生變化時,這個索引表的內容不會同步改變,所以當索引指針往後移動的時候就找不到要迭 代的對象,所以按照 fail-fast 原則 Iterator 會馬上拋出 java .util .ConcurrentModificationException 異常。

  所以 Iterator 在工作的時候是不允許被迭代的對象被改變的。但你可以使用 Iterator 本身的方法 remove() 來刪除對象, Iterator.remove() 方法會在刪除當前迭代對象的同時維護索引的一致性。

  有意思的 是如果你的 Collection / Map 對象實際只有一個元素的時候, ConcurrentModificationException 異常並不會被拋出。這也就是爲什麼在 javadoc 裏面指出: it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.

1 import java .util .*; 
2
3 public final class MyTest 
4 { 
5     private static HashMap p_mapList = new HashMap(2); 
6     private MyTest(){} 
7     public static void init(){ 
8         // If only there are more than one element in Map, 
9         // the ConcurrentModificationException will not be
10         // thrown.
11          p_mapList.put(new String("hello"),new String("world")); 
12          p_mapList.put(new String("goto"),new String("hell")); 
13      } 
14     public static void clear() throws Exception{ 
15          Iterator pTmpKeys = null; 
16          Long pTmpKeyLong; 
17          pTmpKeys = p_mapList.keySet().iterator(); 
18          String pCurKey = null; 
19          String pCurObj = null; 
20         while(pTmpKeys.hasNext()){ 
21              pCurKey = (String) pTmpKeys.next(); 
22              pCurObj = (String) p_mapList.get(pCurKey); 
23
24              p_mapList.put(pCurKey,null); 
25             // You can not remove element in Map object directly.
26             //p_mapList.remove(pCurKey);
27             // But you can remove current element by iterator itself.
28              pTmpKeys.remove(); 
29
30              System.out.println(pCurKey + " removed."); 
31          } 
32          System.out.println(p_mapList.size() +  
33                             " entries left after iterator."); 
34          pTmpKeys = null; 
35      } 
36     public static void main(String[] args) 
37                                  throws Exception{ 
38          MyTest.init(); 
39          MyTest.clear(); 
40      } 
41 } 

發佈了110 篇原創文章 · 獲贊 3 · 訪問量 130萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章