2013-04-19 92 views
2

當我運行下面的一段代碼時,我的程序出現ConcurrentModificationException。通過一些研究,我發現列表中的元素在迭代器循環中無法添加或刪除。我現在要做什麼來移除List<Bean>中的元素?爲什麼從列表中刪除元素會引發ConcurrentModificationException?

for (Iterator<Entry<String, List<Bean>>> iterator = dataMap.entrySet().iterator(); iterator.hasNext();) { 
    Entry<String, List<Bean>> entry = (Entry<String, List<Bean>>)iterator.next(); 
    List<Bean> dateWiseValues = (List<Bean>) entry.getValue(); 
    int j = 0; 
    for (Bean statBean : dateWiseValues) { 
     for (int i = 0; i < commonElements.size(); i++) { 
      if(statBean.getDate().equalsIgnoreCase(commonElements.get(i))) { 
       //remove the bean 
       entry.getValue().remove(j); 
      } 
     } 
     j++; 
    } 
} 
+1

後刪除它,或者你可以將您的值複製到一個「鏡像」列表和循環鏡子,而從實際列表 – 2013-04-19 23:55:44

+0

這消除他們也可能會感興趣:http://docs.oracle.com/javase /1.5.0/docs/api/java/util/concurrent/CopyOnWriteArrayList.html – subarachnid 2013-04-20 00:00:33

+0

@Saraarachnid,那好多了,把它當作答案 – 2013-04-20 00:01:55

回答

5

而不是使用範圍爲基礎的遍歷dateWiseValues,使用Iterator明確,這樣就可以改爲調用Iterator#remove()

for (final Iterator<? extends Bean> it = dateWiseValues.iterator(); 
    it.hasNext();) { 
    final Bean statBean = it.next(); 
    for (int i = 0, last = commonElements.size(); i != last; ++i) 
    if (statBean.getDate().equalsIgnoreCase(commonElements.get(i)))     
     it.remove(); 
} 

在一般情況下,它的安全刪除元素和底層集合,只要通過集合的迭代器之一進行迭代即可。


雖然我們無法看到具體類型的dateWiseValues,我們知道它是List亞型。實施List的兩種常用混凝土類型是ArrayListLinkedList。爲每個類的散文類級別的文檔包含以下警告:此類的iteratorlistIterator方法返回

的迭代器都是快速失敗的:如果列表隨時結構上修改後的迭代器除了通過Iterator自己的removeadd方法創建外,迭代器將拋出ConcurrentModificationException。因此,面對併發修改,迭代器快速而乾淨地失敗,而不是在將來未定的時間冒着任意的,非確定性的行爲冒險。

注意它的警告,你必須迭代過程中使用Iterator#remove()突變,否則你會面臨拋出ConcurrentModificationException您使用的是相同的或任何其他迭代器走在相同的基礎列表中的下一次。

+0

非常感謝!我現在就試試這個。 :) – user1669488 2013-04-20 00:25:07

2

當您使用增強型for循環時,它隱式地在幕後使用Iterator。這是投擲ConcurrentModificationExceptionIterator,而不是您在外部for循環中定義的顯式迭代器iterator。除非您撥打Iterator#remove(),否則您不能從列表中刪除列表,除非您刪除當前列表項並避免ConcurrentModificationException

你兩個選擇:

  • 重寫增強for循環明確使用while循環和Iterator,然後 呼叫remove()當你想刪除的項目。
  • 創建要刪除的項目的List。當您確定要 刪除該項目時,將add刪除到要刪除的項目列表中。然後,在之後, 您已完成迭代,請在原始列表上調用removeAll以刪除您希望刪除的所有項目。