2012-04-28 80 views
1

我試圖從像下面這樣的向量中刪除列表。從Vector中刪除列表獲取java.util.ConcurrentModificationException

public class StringVectorTest { 

private final List<String> stringVector = new Vector<String>(); 

@Test 
public void listRemoveTest(){ 

    List<String> list = stringVector.subList(0, 2); 

    stringVector.removeAll(list); 

    Assert.assertEquals(stringVector.size(), 3); 
} 

@Before 
public void fillList(){ 
    stringVector.add("ABC"); 
    stringVector.add("DEF"); 
    stringVector.add("GEH"); 
    stringVector.add("IJK"); 
    stringVector.add("LMN"); 
} 

}

同時運行測試我得到下面的錯誤

java.util.ConcurrentModificationException 
at java.util.SubList.checkForComodification(AbstractList.java:752) 
at java.util.SubList.listIterator(AbstractList.java:682) 
at java.util.AbstractList.listIterator(AbstractList.java:284) 
at java.util.SubList.iterator(AbstractList.java:678) 
at java.util.AbstractCollection.contains(AbstractCollection.java:82) 
at java.util.Collections$SynchronizedCollection.contains(Collections.java:1563) 
at java.util.AbstractCollection.removeAll(AbstractCollection.java:336) 
at java.util.Vector.removeAll(Vector.java:853) 

我知道,我必須使用一個Iterator克服這個ConcurrentModificationException任何人都可以請讓我知道如何我應該以有效的方式/最佳實踐來使用它?

在此先感謝。

回答

3

做它如下:

public void listRemoveTest() { 
    stringVector.subList(0, 2).clear(); 
    Assert.assertEquals(stringVector.size(), 3); 
} 
+0

感謝很多答案。有效。 – Sam 2012-04-29 02:34:32

2

ConcurrentModificationException的Javadoc中:

此異常可能由已檢測出的對象的併發修改時這種修改是不允許的方法被拋出。 例如,一個線程在另一個線程遍歷它時修改一個集合通常是不允許的。一般來說,在這些情況下迭代的結果是不確定的。某些迭代器實現(包括由JRE提供的所有通用集合實現的實現)可能會選擇在檢測到此行爲時拋出此異常。執行此操作的迭代器稱爲快速迭代器,因爲它們會快速而乾淨地失敗,而不會在將來某個未確定的時間冒着任意的,非確定性的行爲。

注意,此異常並不總是指示對象已經由不同線程併發修改。如果單個線程發出違反對象合約的一系列方法調用,則該對象可能會拋出此異常。例如,如果線程在使用快速迭代器迭代集合的同時直接修改集合,那麼迭代器將拋出此異常。

後者正是你在做什麼(見你發佈的堆棧跟蹤)。由於subList方法返回列表的視圖,所以此方法的返回列表由stringVector支持,因此返回列表中的非結構更改將反映在stringVector中,反之亦然。

所以,你應該用這種「觀點」刪除元素:

@Test 
public void listRemoveTestClearingSubList(){ 
    stringVector.subList(0, 2).clear();  
    Assert.assertEquals(stringVector.size(), 3); 
} 

因爲迭代器是有點棘​​手和醜陋:

@Test 
public void listRemoveTestClearingWithIterator(){ 
    Iterator<String> it = stringVector.iterator(); 
    for (int i = 0; i < 2 && it.hasNext(); i++) { 
     it.next(); 
     it.remove(); 
    } 

    Assert.assertEquals(stringVector.size(), 3); 
} 
+0

非常感謝您的解釋。有用。 :) – Sam 2012-04-29 02:33:41