我想知道为什么我不能从列表中删除元素,当我用foreach-loop迭代它时:
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);
然后删除像:
这样的元素foreach(Object o : objects){
objects.remove(three); //I know that o is my current object
}
似乎foreach-loop不允许删除在循环队列中“仍然”的对象。我是对的吗?
为什么for-int-loop不关心这个?在这个循环中,我可以轻松地删除仍在循环中的对象。
由于
答案 0 :(得分:3)
好吧,最初这个问题被标记为C#,现在被删除了。然而....
如果你从集合中删除一个元素,那么for / loop并不关心。 如果在前进时删除元素,则在删除元素之后将会出现问题索引元素,因为索引与下一个元素不再匹配。 只有当你以相反的顺序(从最后一个元素到第一个元素)循环时才能避免for / loop的问题
foreach在内部遇到同样的问题。枚举器为元素保留Current
位置,如果删除元素然后前进到Next
位置,Current
索引器在删除元素后不会指向该元素,但是在移除一个元素后的两个位置。
例如:
假设一个字符串集合“鸟”,“动物”和“鱼”
foreach并未设计为允许此方案。
答案 1 :(得分:2)
就Java而言,答案在javadoc(强调我的):
此类的迭代器和listIterator方法返回的迭代器是快速失败的:如果在创建迭代器之后的任何时候对列表进行结构修改,除了通过迭代器自己的remove或add方法之外,迭代器将抛出一个ConcurrentModificationException。因此,面对并发修改,迭代器会快速而干净地失败,而不是在未来的未确定时间冒任意,非确定性行为的风险。
答案 2 :(得分:1)
请参阅Calling remove in foreach loop in Java,一般情况下使用Iterator,如果有更多元素,请使用hasNext进行检查
答案 3 :(得分:1)
对于Java至少,你是对的:问题是用于遍历列表中的元素的迭代器不允许修改。它将抛出ConcurrentModificationException。引用java.util.ArrayList
的Java API javadoc此类的迭代器和listIterator返回的迭代器 方法是快速失败的:如果列表在结构上被修改了 创建迭代器之后的时间,除了通过之外的任何方式 迭代器自己删除或添加方法,迭代器会抛出一个 ConcurrentModificationException。因此,面对并发 修改,迭代器快速而干净地失败,而不是 在不确定的时间冒着任意的,非确定性的行为 在将来。
另一种方法是使用允许这种修改的迭代器,而不是ArrayList的默认值或显式创建迭代器,而不是使用foreach循环,并使用它在迭代列表时改变内容的方法