从循环内的List中删除元素

时间:2014-05-14 21:04:29

标签: java arraylist

我正在尝试从循环内的ArrayList中删除一个元素。

没关系。

ArrayList<Integer> list = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
for(Integer i: list){
    if(i == 2)
        list.remove(i);
}

但这不是,并抛出concurrentMOdificationException。

 ArrayList<Integer> list = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
 for(Integer i: list){
        list.remove(i);
 }

我不明白为什么。

我刚刚添加了另一个元素,它也不正常(throw concurrentMOdificationException)。

ArrayList<Integer> list = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4));

System.out.println(list);

for (Integer i : list) {
    if (i == 2)
        list.remove(i);
}

2 个答案:

答案 0 :(得分:4)

使用Iterator类而不是for-each循环。

Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
   Integer i = it.next();
   it.remove();
}

http://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html

  

例如,一个线程通常不允许修改Collection而另一个线程正在迭代它。通常,在这些情况下,迭代的结果是不确定的。如果检测到此行为,某些Iterator实现(包括JRE提供的所有通用集合实现的实现)可能会选择抛出此异常。执行此操作的迭代器称为失败快速迭代器,因为它们快速而干净地失败,而不是在未来的未确定时间冒着任意的,非确定性行为的风险。

     

请注意,此异常并不总是表示某个对象已被另一个线程同时修改。如果单个线程发出违反对象合同的一系列方法调用,则该对象可能会抛出此异常。例如,如果线程在使用失败快速迭代器迭代集合时直接修改集合,则迭代器将抛出此异常。

答案 1 :(得分:0)

当使用这种性质的for循环时,您必须了解一些事情。它实际上是在引擎盖下使用java.util.Iterator。这个迭代器将使用next()方法来确定何时应该停止迭代,并使用hasNext()方法来检索下一个元素。

踢球者只有next()检查并发修改 - hasNext()不执行检查。在第一种情况下,您等到第二次循环迭代从列表中删除2,然后下一次迭代找到列表的结尾并退出。在第二种情况下,在第一次迭代期间从列表中删除1,下一次迭代在尝试检索下一个元素时抛出异常。