2010-07-06 115 views
63

我有下面的代碼:ConcurrentModificationException的ArrayList中爲

private String toString(List<DrugStrength> aDrugStrengthList) { 
    StringBuilder str = new StringBuilder(); 
     for (DrugStrength aDrugStrength : aDrugStrengthList) { 
      if (!aDrugStrength.isValidDrugDescription()) { 
       aDrugStrengthList.remove(aDrugStrength); 
      } 
     } 
     str.append(aDrugStrengthList); 
     if (str.indexOf("]") != -1) { 
      str.insert(str.lastIndexOf("]"), "\n   "); 
     } 
    return str.toString(); 
} 

當我嘗試運行它,我得到ConcurrentModificationException,任何人都可以解釋爲什麼它會發生,即使代碼在同一個線程中運行?我怎麼能避免它?

+3

[你應該停止擔憂和愛情愚弄。(http://blog.stackoverflow.com/2010/11/dr-strangedupe-or-how-我學習的到停止令人擔憂和愛的重複數據刪除/)。 – Will 2011-05-10 20:39:38

+1

對此異常的解釋是ArrayList的迭代器是一個快速失敗的迭代器;即當它檢測到它在同一時間的收集已被修改時它將失敗(拋出異常)。與不引發併發修改異常的故障安全迭代器相比(例如,對集合ConcurrentHashMap和CopyOnWriteArrayList) – 2014-05-28 12:05:18

回答

136

如果您使用「for each」循環瀏覽它,則不能從列表中刪除。您可以使用Iterator。替換:

for (DrugStrength aDrugStrength : aDrugStrengthList) { 
    if (!aDrugStrength.isValidDrugDescription()) { 
     aDrugStrengthList.remove(aDrugStrength); 
    } 
} 

有了:

for (Iterator<DrugStrength> it = aDrugStrengthList.iterator(); it.hasNext();) { 
    DrugStrength aDrugStrength = it.next(); 
    if (!aDrugStrength.isValidDrugDescription()) { 
     it.remove(); 
    } 
} 
+0

java的foreach語法實際上使用Iterator,一些IDE會報告這個解決方案,並建議用foreach替換(for(MyListener listener:MyListenerList)) – 2014-12-29 09:42:14

+0

@HugoGresse是的,但這是相反的方向。迭代器公開了對其迭代安全的'remove',這是foreach「失敗」的事情。 – 2014-12-30 21:52:31

+2

不知道,謝謝@KonradGarus – 2014-12-31 08:08:14

5

在遍歷循環時,您試圖在remove()操作中更改List值。這將導致ConcurrentModificationException。

按照下面的代碼,這將實現你想要的,但不會引發任何異常

private String toString(List aDrugStrengthList) { 
     StringBuilder str = new StringBuilder(); 
    List removalList = new ArrayList(); 
    for (DrugStrength aDrugStrength : aDrugStrengthList) { 
     if (!aDrugStrength.isValidDrugDescription()) { 
      removalList.add(aDrugStrength); 
     } 
    } 
    aDrugStrengthList.removeAll(removalList); 
    str.append(aDrugStrengthList); 
    if (str.indexOf("]") != -1) { 
     str.insert(str.lastIndexOf("]"), "\n   "); 
    } 
    return str.toString(); 
} 
+0

爲什麼downvote? – bragboy 2010-07-06 09:20:52

+2

'aDrugStrengthList.removeAll(removalList)' – 2010-07-06 09:25:37

+0

@TimBender - 謝謝你編輯了答案。 – bragboy 2016-03-07 14:51:43

22

像其他的答案說,你不能從你遍歷集合中刪除的項。您可以通過明確使用Iterator並刪除該項目來解決此問題。

Iterator<Item> iter = list.iterator(); 
while(iter.hasNext()) { 
    Item blah = iter.next(); 
    if(...) { 
    iter.remove(); // Removes the 'current' item 
    } 
} 
5

應該有List接口支持這種操作的同時FPGA實現。

嘗試java.util.concurrent.CopyOnWriteArrayList.class

+0

我和HashMap有同樣的問題,用Map接口的另一個實現 修正。 你應該自己測試一下。我不知道有關CopyOnWriteArrayList – idiotgenius 2010-07-06 13:35:21

12

我喜歡反向順序循環,例如:

int size = list.size(); 
for (int i = size - 1; i >= 0; i--) { 
    if(remove){ 
     list.remove(i); 
    } 
} 

,因爲它不需要學習任何新的數據結構或類。

+0

的詳細信息,謝謝。我不知道這個竅門。 – 2018-01-30 14:40:21

相關問題