关于java:Foreach对于for(int …)循环 – 为什么foreach在删除元素时会引发异常?

Foreach against for(int…) loop - why does foreach raises exceptions when removing elements?

本问题已经有最佳答案,请猛点这里访问。

我想知道为什么我不能从列表中删除元素,当我用foreach循环迭代它时,比如:

1
2
3
4
5
6
7
8
List<Object> objects = new ArrayList<Object>();
Object one = new Object();
Object two = new Object();
Object three = new Object();

objects.add(one);
objects.add(two);
objects.add(three);

然后移除这些元素:

1
2
3
foreach(Object o : objects){
  objects.remove(three); //I know that o is my current object
}

似乎foreach循环不允许删除循环队列中"仍在"的对象。我说的对吗?

为什么for int循环不关心这个?在这个循环中,我可以轻松地删除仍在循环中的对象。

谢谢


嗯,最初这个问题被标记为"C",现在被删除了。然而。。。。

for/loop不关心是否从集合中移除元素,这不是真的。如果在继续操作时删除元素,则在删除元素后索引元素将出现问题,因为索引不再与下一个元素匹配。只有以相反的顺序循环(从最后一个元素到第一个元素),才能避免for/loop问题。

前臂内部也有同样的问题。枚举器对元素保持一个Current位置,如果删除元素,然后前进到Next位置,则Current索引器不会指向删除后的元素,而是指向删除后的元素2位置。

例如:

假设一系列"鸟"、"动物"和"鱼"的集合

  • 前臂开始时,内部电流为0(指向"鸟")。
  • 删除"birds",则"animals"位于索引0(当前仍指向该索引)
  • 前进到下一个元素(current=1,指向"fish")。
  • 没有例外,下一步将退出循环。

foreach的设计不允许出现这种情况。


就Java而言,答案是在JavaDoc(强调雷)中:

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.


至少对于Java来说,您是正确的:问题是用于遍历列表中元素的迭代器不允许修改。它将抛出一个ConcurrentModificationException。引用JavaAPI JavaDoc为JavaUTIL.ARAYLIST

The iterators returned by this class's iterator and listIterator
methods are fail-fast: if the list is structurally modified at any
time after the iterator is created, in any way except through the
iterator's own remove or add methods, the iterator will throw a
ConcurrentModificationException. Thus, in the face of concurrent
modification, the iterator fails quickly and cleanly, rather than
risking arbitrary, non-deterministic behavior at an undetermined time
in the future.

另一种方法是使用允许此类修改的迭代器,而不是arraylist的默认值,或者显式创建迭代器,而不是使用foreach循环,并使用它在遍历列表时必须更改内容的方法。


参见Java中Frach循环中的调用移除,一般使用迭代器,如果有更多元素,则与HasNew检查