2013-08-26 51 views
4

當我運行下面的代碼:爲什麼我會得到java.util.ConcurrentModificationException?

import java.util.LinkedList; 

    class Tester { 
     public static void main(String args[]) { 
     LinkedList<String> list = new LinkedList<String>(); 
     list.add(new String("suhail")); 
     list.add(new String("gupta")); 
     list.add(new String("ghazal")); 
     list.add(new String("poetry")); 
     list.add(new String("music")); 
     list.add(new String("art")); 

     try { 
      for(String s : list) { 
      list.add(0,"art"); 
      list.remove(6); 
      System.out.println(list); 
     } 
     }catch(Exception exc) { 
      exc.printStackTrace(); 
     } 

    } 
} 

我得到的是說,一個例外:

java.util.ConcurrentModificationException 
    at java.util.LinkedList$ListItr.checkForComodification(Unknown Source) 
    at java.util.LinkedList$ListItr.next(Unknown Source) 
    at Tester.main(Tester.java:14) 

爲什麼會出現這種異常?

編輯:tmpList是一個LinkedList,其每個節點包含一個DepConfAttr類型的對象。我正在基於內存(最高內存優先)排序tmpList,這是DepConfAttr對象的屬性之一。

上面的代碼反映了什麼,我想通過下面的代碼

int size = tmpList.size(); 
     int elementBC = 0; // element being checked 
     int startIndex = 1; 
     for (DepConfAttr dca : tmpList) { 
      long maxMem = dca.getMemory(); // Let this be the maximum memory 
      for(int i = startIndex ; i < size ; i++) { 
       DepConfAttr dcaTmp = tmpList.get(i); 
       if(maxMem < dcaTmp.getMemory()) { 
        tmpList.add(elementBC, dcaTmp); 
        tmpList.remove(i+1); 
        maxMem = tmpList.get(elementBC).getMemory();       
       } 
      } 
      elementBC++; 
      startIndex++; 
      size--; 
     } 
+2

重複時不要刪除。 –

+2

你到底想要做什麼?我沒有看到你在循環中的任何地方使用's'? –

+0

您正在迭代時添加和刪除。因此你有一個併發修改。爲了理解你應該做什麼,你必須去做你真正想做的事情,這是不明確的。 –

回答

10

爲什麼我收到此異常實現?

您正在從列表中刪除一個項目,而不是通過迭代器,而迭代它。在迭代時,您還將添加到列表中。

這並不是真的很清楚你想在這裏實現什麼,但除了併發集合之外,當你嘗試這樣做時,你總會得到一個異常。

對此的一個常見修復方法是首先創建列表的副本並對其進行迭代,隨時修改原始內容。

+0

此問題的確切答案 – Prabhaker

+0

edited問題 –

+0

@SuhailGupta:有很多更好的排序方法 - 使用'Collections.sort'與自定義比較器,但最好不要使用LinkedList。 (首先將其複製到一個ArrayList中。) –

2

在遍歷列表時,無法從中刪除項目。這樣做會導致異常。

做:

int size = list.size(); 
for (int i = 0 ; i< size ; i++) { 
    list.add(0,"art"); 
    list.remove(6); 
    System.out.println(list); 
} 
1

的問題是,你直接修改List而一個Iterator正試圖在其上運行。當您下次告知Iterator迭代(隱式地在for循環中)時,它會通知List已從其下方更改並引發異常。

相反,如果你需要修改的列表,同時穿越它,抓住Iterator明確並使用它:

List<String> list = .... 
Iterator<String> iterator = list.iterator(); 
while (iterator.hasNext()) { 
    String s = iterator.next(); // must be called before you can call iterator.remove() 
    iterator.remove(); 
} 

您仍然無法插入List而這是怎麼回事,這韓元不要讓你刪除任意元素,只是當前的元素。

+1

他不會刪除當前元素,而是刪除索引6中的元素。所以這不會起作用。坦率地說,這個問題不是很清楚。 –

-1

你需要明確地使用迭代器才能工作。例如:

Iterator<String> iter = li.iterator(); 
    while(iter.hasNext()){ 
    if(iter.next().equalsIgnoreCase("some value")) 
     iter.remove(); 
    } 
    } 

此處瞭解詳情:http://www.coderanch.com/t/233932/threads/java/deal-Concurrent-Modification-Exception但只是谷歌的例外,你會發現很多的例子。

+1

你正在使用併發集合 - *這是*這裏有什麼區別,而不是迭代器。 –

+0

它只是其中的一個例子,這兩個例子都使用了迭代器。 – Kris

+0

你的兩個例子都使用併發集合。如果您使用非併發集合,則兩者都會失敗。請注意,增強的for循環也使用迭代器。 –

0

問題是在對其使用隱式迭代器時對列表進行更改。對於引用代碼,最簡單的辦法是不使用迭代器都:

for(int i=0; i<list.size(); i++) { 
    list.add(0,"art"); 
    list.remove(6); 
    System.out.println(list); 
} 

您可能需要發佈更多現實的代碼,以最佳的解決方案獲得建議。如果您想要在遍歷列表時刪除當前項目,請使用顯式迭代器循環,並使用Iterator的remove()方法。在其他情況下,最好的解決方案是爲循環內的更改形成一個計劃,但之後再執行。例如,在循環列表過程中,構建一個removeList,其中包含要刪除的元素的索引列表。在removeList的單獨循環中,從列表中刪除這些元素。

0

因爲您同時(同時)修改和迭代集合。 Java不喜歡這個

既然你不實際使用S,你可以使用標準的for循環

for(int i=0; i< list.size(); i++) { 
     list.add(0,"art"); 
     list.remove(6); 
     System.out.println(list); 
} 
0

通過名單,並在當你同時迭代時,ConcurrentModificationException的拋出試圖通過另一個線程或循環來修改(添加/刪除)列表的內容。

你可以嘗試使用ConcurrentLinkedQueue或約翰說做一個副本,並修改原來的迭代。

Queue<String> list = new ConcurrentLinkedQueue<String>(); 

list.add("suhail"); 
list.add("gupta"); 
list.add("ghazal"); 
list.add("poetry"); 
list.add("music"); 
list.add("art"); 

int size = list.size(); 

for(int i = 0; i < size; i++){ 
    list.add("art"); 
    list.remove("art"); 
    System.out.println(list); 
} 
相關問題