【问题标题】:Why is using the for-each loop on an ArrayList not working? [duplicate]为什么在 ArrayList 上使用 for-each 循环不起作用? [复制]
【发布时间】:2016-01-15 11:48:31
【问题描述】:

我有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);
}

如果你添加一个迭代器并使用一个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&lt;String&gt;。 是不是因为 ArrayList 没有某种迭代能力,尽管它是 subclass of Collection

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

【问题讨论】:

标签: java exception arraylist


【解决方案1】:

如果在迭代 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);
}

如您所见,创建了一个交互器,但直接修改了列表。 list 只能由用于迭代它的迭代器 i 修改。

【讨论】:

  • 您错过了对 next 的呼叫 :)
  • 你是对的,谢谢!
  • modifying 是指只删除还是添加元素有同样的问题?
  • @hamena314 添加时不一定有问题,但您不能确定。实现可能会有所不同。所以使用迭代器进行修改是唯一保证安全的方式。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    for 在内部使用迭代器。但是你直接删除就行了=> CME。删除后对next的内部调用会抛出它,因为它发现列表已修改。

    while 的示例中,您通过迭代器删除,效果很好。

    【讨论】:

      【解决方案4】:

      从集合中删除对象时,使用 ITERATORS

      您的代码不起作用,因为您在循环访问集合时正在修改集合。根据 Oracle 的 javadoc,唯一安全的方法是使用迭代器

      请注意,Iterator.remove() 是在迭代期间修改集合的唯一安全方法;如果在迭代过程中以任何其他方式修改了底层集合,则行为是未指定的。

      看看this for further infos

      【讨论】:

        猜你喜欢
        • 2010-10-17
        • 1970-01-01
        • 1970-01-01
        • 2012-04-06
        • 2021-05-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-01
        相关资源
        最近更新 更多