使用 for-each 循环进行迭代时,“删除”函数如何对 ArrayList 起作用?

2023-12-22

我有一个非常基本的问题。

我创建了简单的ArrayList我正在使用 for-each 循环迭代时删除该项目。它给了我java.util.ConcurrentModificationException因为我无法在迭代时删除项目但是当我取消评论时if状况良好.

请任何人都可以解释一下 for-each 是如何以这种方式工作的。

    ArrayList<String> list1 = new ArrayList<String>();
    list1.add("Hello");
    list1.add("World");
    list1.add("Good Evening");

    for (String s : list1) {
        //if (s.equals("World")) {
            list1.remove(1);
        //}
    }

如果我把它改成list1.remove(2); or list1.remove(0);那么它的工作也很好。

Note:这是示例代码,我知道使用它可以正常工作Iterator。我这个问题的唯一目的是知道如何方法remove()如果条件未注释,则无论您从列表中删除哪个索引,都可以完美运行。


该列表有一个名为的变量modCount,这意味着“修改计数”。每当你打电话时remove(或执行其他结构修改),它增加了modCount.

如果您在不通知迭代器的情况下添加或删除元素,迭代器将无法跟踪其在列表中的位置。因此,作为安全检查,在迭代开始时,迭代器会记下modCount,另存为expectedModCount。当从迭代器读取每个项目时,迭代器会检查以确保modCount仍然等于预期值,如果不等于则抛出异常。

通常,如果列表在迭代期间被不安全地修改,这将成功导致抛出异常。然而,在这种情况下这还不够,当if语句已启用。阅读完您的代码后"World",该项目已被删除,因此列表现在包含["Hello", Good Evening"]。迭代器仍然位于位置 1(现在包含"Good Evening")并且当它尝试读取下一个项目时,它发现它现在已经到达列表的末尾,所以它不费心去检查modCount。因此,也不例外。

请注意中的警告ConcurrentModificationException 文档 http://docs.oracle.com/javase/8/docs/api/java/util/ConcurrentModificationException.html:“一般来说,在存在不同步并发修改的情况下不可能做出任何硬保证。快速失败操作会尽力抛出 ConcurrentModificationException。”

即使在这种情况下没有抛出异常,代码仍然是错误的。要在迭代时删除元素,必须使用迭代器自己的remove method:

for (Iterator<String> it = list1.iterator(); it.hasNext();) {
    String s = it.next();
    if (s.equals("World")) {
        it.remove();
    }
}

这样,迭代器就知道列表已更改并且仍然可以正确迭代。

或者,您可以从列表的临时副本进行迭代:

for (String s : new ArrayList<>(list1)) {
    if (s.equals("World")) {
        list1.remove(...);
    }
}

尽管在这个简单的情况下,您甚至不需要这样做;你可以写:

list1.remove("World");
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 for-each 循环进行迭代时,“删除”函数如何对 ArrayList 起作用? 的相关文章

随机推荐