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

ham*_*314 2 java exception arraylist

偶然发现了这个代码,它抛出了一个ConcurrentModificationException

ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d"));

for (String s : list) {
    if (s.equals("a"))
        list.remove(s);
}
Run Code Online (Sandbox Code Playgroud)

如果你添加一个迭代器并使用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();
    }
}
Run Code Online (Sandbox Code Playgroud)

我不明白,为什么有必要Iterator<String>在这种情况下使用.是因为ArrayList没有某种迭代能力,尽管它是Collection子类

是否有必要使用while循环,或者您是否可以生成带有for循环的版本?

R.C*_*sta 7

你的链接实际上解释得很好:

在foreach循环中,编译器会在删除元素的操作之后调用.next(),这会导致ConcurrentModificationException.


Tob*_*ías 7

如果Collection在迭代时修改了a,则在大多数实现ConcurrentModificationException中抛出a.

"foreach"版本:

for (String s : list) {
    if (s.equals("a"))
        list.remove(s);
}
Run Code Online (Sandbox Code Playgroud)

内部相当于

for(Iterator<String> i = list.iterator(); i.hasNext(); ) {
    String s = i.next();
    if (s.equals("a"))
        list.remove(s);
}
Run Code Online (Sandbox Code Playgroud)

如您所见,创建了一个interator,但直接修改了列表.在list只能由迭代器被修改i用于迭代它.

  • @ hamena314添加时不一定是个问题,但你不能确定.实施可能会有所不同.因此,使用迭代器进行修改是唯一有保障的安全方法. (3认同)