2012-04-28 72 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