我stumbled upon this code,会抛出ConcurrentModificationException
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));
for (String s : list) {
if (s.equals("a"))
list.remove(s);
}
如果添加Iterator并使用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();
}
}
我不明白,为什么有必要在这种情况下使用Iterator<String>
。
是因为ArrayList没有某种迭代能力,尽管它是subclass of Collection?
是否有必要使用while循环,还是可以生成带有for循环的版本?
答案 0 :(得分:7)
您的链接实际上解释得非常好:
在foreach循环中,编译器会在删除元素的操作之后调用.next(),这会导致ConcurrentModificationException。
答案 1 :(得分:7)
如果在迭代时修改Collection
,则在大多数实现中,会抛出ConcurrentModificationException
。
“foreach”版本:
for (String s : list) {
if (s.equals("a"))
list.remove(s);
}
内部相当于
for(Iterator<String> i = list.iterator(); i.hasNext(); ) {
String s = i.next();
if (s.equals("a"))
list.remove(s);
}
如您所见,创建了一个interator,但直接修改了列表。 list
只能由用于迭代它的迭代器i
修改。
答案 2 :(得分:3)
for
在内部使用迭代器。但你直接在列表中删除=&gt; CME。删除后对next
的内部调用将抛出它,因为它找到了修改的列表。
在带有while
的示例中,您通过迭代器删除,该工作正常。
答案 3 :(得分:1)
从集合中删除对象时,请使用 ITERATORS
您的代码不起作用,因为您在循环时修改集合。根据Oracle的 javadoc ,唯一安全的方法是使用迭代器。
请注意, Iterator.remove()是在迭代期间修改集合的唯一安全方法;如果在迭代进行过程中以任何其他方式修改基础集合,则行为未指定。