我试图从下面的矢量中删除列表。
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
任何人都可以让我知道我应该如何以有效的方式/最佳实践使用它?
提前致谢。
答案 0 :(得分:3)
执行以下操作:
public void listRemoveTest() {
stringVector.subList(0, 2).clear();
Assert.assertEquals(stringVector.size(), 3);
}
答案 1 :(得分:2)
来自ConcurrentModificationException的javadoc:
当不允许进行此类修改时,检测到并发修改对象的方法可能抛出此异常。 例如,一个线程通常不允许修改Collection而另一个线程正在迭代它。通常,在这些情况下,迭代的结果是不确定的。如果检测到此行为,某些Iterator实现(包括JRE提供的所有通用集合实现的实现)可能会选择抛出此异常。执行此操作的迭代器称为 fail-fast iterators ,因为它们快速而干净地失败,而不是在未来的未确定时间冒着任意的,非确定性行为的风险。
请注意,此异常并不总是表示某个对象已被其他线程同时修改。如果单个线程发出违反对象合同的一系列方法调用,则该对象可能会抛出此异常。例如,如果线程在使用故障快速迭代器迭代集合时直接修改集合,则迭代器将抛出此异常。
后者正是您正在做的事情(请参阅您发布的堆栈跟踪)。当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);
}