如何同时使用迭代for-each循环删除ArrayList的作品? [英] How remove works for ArrayList while iterating using for-each loop?

查看:122
本文介绍了如何同时使用迭代for-each循环删除ArrayList的作品?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a very basic question.

我创建了简单的的ArrayList ,我删除的项目,而使用for-each循环迭代。它给了我 java.util.ConcurrentModificationException ,因为在迭代,但我不能删除项目的当我取消注释如果状态正常工作

I have created simple ArrayList and I am removing the item while iterating using for-each loop. It gives me java.util.ConcurrentModificationException because I can't remove an item while iterating but when I un-comment the if condition it works fine.

请任何人可以给我解释一下怎么换每个这样的作​​品。

Please can anybody explain me how for-each works in this way.

    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); list1.remove(0); 然后也是其工作的罚款。

If I change it to list1.remove(2); or list1.remove(0); then also its working fine.

注意:这是示例code,我知道它会正常工作使用的Iterator 。我这个问题的唯一目的是要懂得方法删除()完美的作品,如果条件是取消注释不管你是从列表中删除什么指数。

Note: This is sample code and I know it will work fine using Iterator. My sole purpose of this question is to know how method remove() works perfectly if condition is un-commented no matter what index you are removing from the list.

推荐答案

该列表中有一个名为modCount的变量。每当你叫删除(或执行其他结构上的修改),它增加了modCount的。

The list has a variable called modCount. Whenever you call remove (or perform other structural modifications), it increments the modCount.

在迭代的开始,迭代器使得一记modCount的的,将其保存为expectedModCount。当每个项目是从迭代读取,迭代器检查是否modCount的等于预期的值,并且如果它不

At the start of iteration, the iterator makes a note of the modCount, saving it as expectedModCount. When each item is read from the iterator, the iterator checks if the modCount equals the expected value, and throws an exception if it doesn't.

通常,这将导致成功如果列表迭代过程中不安全修改抛出异常。但是,当启用if语句时,它不是在这种情况下就足够了。您code已经阅读世界之后,该项目被删除,因此列表现在包含 [你好,晚上好 ] ,迭代器仍然是在位置1处(现在包含晚上好),当它试图读取下一个项目,它找到它现在已经达到了列表的末尾,所以它不打扰检查modCount的,因此,也不例外。

Usually, this will successfully cause the exception to be thrown if the list is unsafely modified during iteration. However, it's not sufficient in this case when the if statement is enabled. After your code has read "World", that item is removed, and so the list now contains ["Hello", Good Evening"]. The iterator is still at position 1 (which now contains "Good Evening") and when it tries to read the next item, it finds it has now reached the end of the list, so it doesn't bother to check the modCount. Hence, no exception.

注意 ConcurrentModificationException的文档:它是,一般来说,不可能作出任何硬性保证不同步并发修改的presence快速失败的操作抛出ConcurrentModificationException尽最大努力的基础上

Note the caveat in the ConcurrentModificationException documentation: "It is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast operations throw ConcurrentModificationException on a best-effort basis."

在code仍然是错的,即使它不会发生在抛出异常在这种情况下。要删除一个元素,而迭代,你必须使用迭代器自身的删除方法:

The code is still wrong though, even if it doesn't happen to throw the exception in this case. To remove an element while iterating, you must use the iterator's own remove method:

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

这样,迭代器知道列表已发生变化,仍然可以正常进行迭代。

That way, the iterator knows that the list has changed and can still iterate correctly.

另外,你可以从列表中的副本迭代:

Alternatively, you can iterate from a copy of the list:

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

虽然,在这个简单的例子,你甚至都不需要做的是什么;你可以这样写:

Although, in this simple case, you don't even need to do that; you can just write:

list1.remove("World");

这篇关于如何同时使用迭代for-each循环删除ArrayList的作品?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆