java 为什么在 ArrayList 上使用 for-each 循环不起作用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34810407/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is using the for-each loop on an ArrayList not working?
提问by hamena314
I've stumbled upon this code, which throws a ConcurrentModificationException
我偶然发现了这段代码,它抛出了一个ConcurrentModificationException
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
for (String s : list) {
if (s.equals("a"))
list.remove(s);
}
If you add an Iterator and use a while-loop, the code works fine:
如果添加迭代器并使用 while 循环,则代码可以正常工作:
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
String s = iter.next();
if (s.equals("a")) {
iter.remove();
}
}
I dont understand, why it is necessary, to use Iterator<String>
in this case.
Is it because of the ArrayList not having some sort of ability to get iterated, altough it is a subclass of Collection?
我不明白为什么有必要Iterator<String>
在这种情况下使用。是不是因为 ArrayList 没有某种迭代能力,尽管它是Collection的子类?
Is it necessary to use the while-loop, or could you produce a version with a for-loop?
是否有必要使用 while 循环,或者您可以生成带有 for 循环的版本吗?
回答by R.Costa
Your link actually explains it pretty well:
您的链接实际上很好地解释了它:
In the foreach loop, compiler will make the .next() called after the operation of removing element, which caused the ConcurrentModificationException.
在foreach循环中,编译器会在删除元素的操作后调用.next(),导致ConcurrentModificationException。
回答by Tobías
If a Collection
is modified while iterating over it, in most of the implementations, a ConcurrentModificationException
is thrown.
如果 aCollection
在迭代时被修改,在大多数实现中, a 会ConcurrentModificationException
被抛出。
The "foreach" version:
“foreach”版本:
for (String s : list) {
if (s.equals("a"))
list.remove(s);
}
internally is equivalent to
内部相当于
for(Iterator<String> i = list.iterator(); i.hasNext(); ) {
String s = i.next();
if (s.equals("a"))
list.remove(s);
}
As you can see, an interator is created, but the list is modified directly. The list
can only be modified by the iterator i
used to iterate over it.
如您所见,创建了一个 interator,但直接修改了列表。在list
只能由该迭代器被修改i
过它用于迭代。
回答by Fildor
The for
uses an iterator internally. But you delete on the list directly => CME. The internal call to next
after the deletion will throw it because it finds the list modified.
在for
内部使用迭代器。但是你直接删除就行了=>CME。next
删除之后的内部调用会抛出它,因为它发现列表被修改了。
In the example with while
, you delete through the iterator, which works fine.
在带有 的示例中while
,您通过迭代器删除,这工作正常。
回答by Davide Spataro
When removing object from collections, use ITERATORS
从集合中删除对象时,使用迭代器
Your code does not work because you are modifying the collection while looping over it. According to Oracle's javadocthe only safe way to do it is using iterators.
您的代码不起作用,因为您在循环时修改了集合。根据 Oracle 的javadoc,唯一安全的方法是使用 iterators。
Note that Iterator.remove()is the only safe way to modify a collection during iteration; the behavior is unspecified if the underlying collection is modified in any other way while the iteration is in progress.
请注意,Iterator.remove()是在迭代期间修改集合的唯一安全方法;如果在迭代过程中以任何其他方式修改了基础集合,则行为是未指定的。
Have a look at this for further infos
看看这个了解更多信息