java 遍历列表时获取 ConcurrentException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5644568/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 12:03:48  来源:igfitidea点击:

Getting ConcurrentException when traversing a list

javalistiteratorfor-loopforeach

提问by M.J.

I am in a very peculiar state. I have a list something like below :-

我处于一种非常奇特的状态。我有一个类似于下面的列表:-

List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");

Now when i do multiple type of traversing, like using advanced for, iterator, and normal for loop, below are the sample code snippets :-

现在,当我进行多种类型的遍历时,例如使用高级 for、迭代器和普通 for 循环,以下是示例代码片段:-

1> Advanced Loop :-

1> 高级循环:-

try {
    for(String a : list) {
        System.out.println(a);
        list.add("f");
    }
} catch (Exception e) {
    e.printStackTrace();
}

2> Iterator :-

2> 迭代器:-

try {
    Iterator<String> itr =  list.iterator();
    while(itr.hasNext()) {
        System.out.println(itr.next());
        list.add("f");
    }
} catch (Exception e) {
    e.printStackTrace();
}

3> Normal Loop :-

3> 正常循环:-

for (int i=0;i<list.size();i++) {
    System.out.println(list.get(i));
    list.add("f");
}

Now, the peculiar problem is, that when using advanced for-loop and iterator, i get the following exception : -

现在,特殊的问题是,当使用高级 for 循环和迭代器时,我得到以下异常:-

java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
    at java.util.ArrayList$Itr.next(Unknown Source)


the reason i know, that while iterating through a list, one cannot modify it parallely.

but when i use the normal for loop, then it works properly, Am i missing something??

但是当我使用普通的 for 循环时,它可以正常工作,我错过了什么吗??

Please Help!!!..

请帮忙!!!..

回答by sbridges

If you modify a List, it invalidates any Iterator objects created from it. The advanced loop (1) compiles to nearly the same code as the iterator loop (2), meaning that there is an Iterator object created behind the scenes.

如果你修改一个 List,它会使任何从它创建的 Iterator 对象失效。高级循环 (1) 编译为与迭代器循环 (2) 几乎相同的代码,这意味着在幕后创建了一个 Iterator 对象。

The javadocs for ConcurrentMOdificationExceptionhave more details.

ConcurrentMOdificationException的 javadocs有更多细节。

If you want to add while iterating, use

如果要在迭代时添加,请使用

ListIterator listIter = ...
while(listIter.hasNext())
{
    if(shouldAdd(iter.next())) {
        iter.add(....)
    }
}

回答by Mike Lewis

The advanced loop is just syntactic sugar for the iterator. The iterator always calls checkForComodification()whenever it runs next(). This method will throw an exception if it sees that you modified the list.

高级循环只是迭代器的语法糖。迭代器checkForComodification()在运行时总是调用next()。如果此方法看到您修改了列表,则会抛出异常。

Running the "Normal Loop" does not provide this functionality of checking the modification count because you aren't using an iterator to loop, you are strictly using the for loop construct.

运行“正常循环”不提供检查修改计数的功能,因为您没有使用迭代器进行循环,而是严格使用 for 循环构造。

回答by Chris Dennett

Doing a for loop on the list will create serious problems. You'll get entries being re-read (deleting a previous entry might cause this) and you might get IndexOutOfBoundsExceptions. Use CopyOnWriteArrayListfor a concurrent-safe list with not that much overhead, depending on your application. If you have many writes to the list, use ConcurrentLinkedQueue, but be aware that this acts like a queue and you can only do queue-like stuff with it like only adding to the end and removing from the front.

在列表上执行 for 循环会产生严重的问题。您将重新读取条目(删除前一个条目可能会导致此问题),并且您可能会收到 IndexOutOfBoundsExceptions。将CopyOnWriteArrayList用于并发安全列表,开销不大,具体取决于您的应用程序。如果您有很多写入列表,请使用ConcurrentLinkedQueue,但请注意,这就像一个队列,您只能使用它执行类似队列的操作,例如仅添加到末尾和从前面删除。

回答by satish

You should keep in mind that the ConcurrentModificationException is thrown by the Iterator's next method, but not by the List's add method. This means, the list is actually modified when you add a new element in the loop. If you quit the loop after adding a new element, there is no exception thrown and the element is added to the list.

您应该记住,迭代器的 next 方法抛出 ConcurrentModificationException,而不是 List 的 add 方法。这意味着,当您在循环中添加新元素时,实际上会修改列表。如果在添加新元素后退出循环,则不会抛出异常并将该元素添加到列表中。

Otherwise you can use Iterator's add and remove method to modify the list inside the loop.

否则,您可以使用 Iterator 的 add 和 remove 方法来修改循环内的列表。