为什么在ArrayList上使用for-each循环不起作用?

时间:2016-01-15 11:48:31

标签: java exception arraylist

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循环的版本?

4 个答案:

答案 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()是在迭代期间修改集合的唯一安全方法;如果在迭代进行过程中以任何其他方式修改基础集合,则行为未指定。

查看this for further infos