2015-02-09 66 views
0

以下代碼在特定映射中存在多個修改時正常工作。但只有一個修改時,它會引發併發修改異常爲什麼拋出併發修改異常

for(Map.Entry<String, List<String>> mapEntry : beanMap.entrySet()) { 
    for(String dateSet : dateList) { 
     String mName = mapEntry.getKey(); 
     boolean dateFound = false; 
     if(beanMap.containsKey(dateSet)) { 
      dateFound = true; 
      System.out.println(" Found : "+mapEntry.getKey()); 
     } 
     if(!dateFound) 
     { 
      Map<String, List<String>> modifiedMap = beanMap; 
      List<String> newBeanList = new ArrayList<String>(); 
      dBean beanData = new Bean(dateSet+"NA","NA","NA",0,0,0); 
      newBeanList.add(beanData); 
      System.out.println(" Adding : "+dateSet+" "+"NA"); 
      modifiedMap.put(mName, newBeanList); 
     } 
    } 
} 

在修改「modifiedMap」當僅一次它拋出ConcurrentModificationException的上面的代碼。可能還有更多,但無法找出原因。

回答

6

當您使用增強型for循環時,暗示Iterator在幕後工作。您嘗試使beanMap複製這一行:

Map<String, List<String>> modifiedMap = beanMap; 

然而,這僅僅創建另一個參考變量也指在同一個地圖對象。還有隻有一個地圖,並且要修改它:

modifiedMap.put(mName, newBeanList); 

Iterator然後檢測,當它試圖遍歷到下一個條目,導致ConcurrentModificationException地圖被修改。

您可以創建另一個Mapnewput您在迭代原始地圖時對該地圖所做的所有修改。

完成迭代原始地圖後,您可以調用the putAll method,傳遞新地圖以應用所需的所有修改。

+0

或者像這樣在迭代中使用Iterator Iterator >> iterator = beanMap.entrySet()。iterator(); iterator.hasNext(); 哪個更好? – 2015-02-09 17:39:45

+0

另一種選擇是在開始迭代器時創建原始副本,例如對於(Map.Entry > mapEntry:new ArrayList(beanMap.entrySet())) – Ken 2015-02-09 17:40:23

+0

@ user1629109即使您使用顯式的'Iterator',它在修改地圖時仍可能拋出'ConcurrentModificationException'。這裏的關鍵是避免修改地圖,因爲你用'Iterator'迭代它。 – rgettman 2015-02-09 17:42:37

0

您不允許在使用此語法對其進行迭代時更改底層集合。這些集合以快速失敗的方式實現,因此即使是單個更改也會引發異常。

如果您在訪問元素時需要更改集合,請使用Iterator

+0

您是否可以在OP中指定的代碼中添加相關更改? – 2015-02-09 17:36:11

0

modifiedMap是對您正在迭代的相同地圖beanMap的引用。您在迭代時修改Collection modifiedMap,因此異常。

+0

我同意。我知道那在繼續。但是,解決方案是什麼?我無法創建modifiedMap的新實例。 – 2015-02-09 17:38:02

+0

很多解決方法。一種方法是做一個你的地圖的深層副本並修改它。 – 2015-02-09 17:57:57

相關問題