java 为什么 Iterator.next() 会抛出 ConcurrentModificationException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6067612/
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 14:11:08  来源:igfitidea点击:

Why Iterator.next() throws ConcurrentModificationException

javaiteratorwhile-loop

提问by JBoy

Strangly enough, this small piece of code throws the above mentioned Exception. Also, looking at code posted around the web this seems to be correct:

奇怪的是,这一小段代码抛出了上面提到的异常。此外,查看网上发布的代码,这似乎是正确的:

import java.util.ArrayList;
import java.util.Iterator;

public class IteratorTest {

    ArrayList<Integer> arr = new ArrayList<Integer>();

    Iterator i = arr.iterator();

    public void show() {
        arr.add(2);
        arr.add(5);
        arr.add(9);

        while(i.hasNext()){
            System.out.println(i.next());
        }
    }
}

Any advice? Thanks

有什么建议吗?谢谢

采纳答案by anubhava

This call:

这个电话:

Iterator i=arr.iterator();

should be after you've done all the writes into your ArrayList.

应该在您完成对 ArrayList 的所有写入之后。

So in your code do this just before you start iterating like this:

因此,在您开始像这样迭代之前,在您的代码中执行此操作:

Iterator i=arr.iterator();
while(i.hasNext()) {
...
}

回答by Steve Kuo

It's because you've modified the backing list between getting the Iterator via iterator()and calling next().

这是因为您已经修改了通过iterator()和调用获取迭代器之间的支持列表next()

The typical usage of an Iterator is:

Iterator 的典型用法是:

for (Iterator<Integer> iter=arr.iterator(); iter.hasNext(); ) {
    Integer element = iter.next();
}

Or better yet, use the new for-each loop:

或者更好的是,使用新的 for-each 循环:

for (Integer element: arr) {
}

Make sure to to perform additions to the Collection outside of the loop.

确保在循环之外对集合执行添加。

回答by pickypg

You are defining the Iteratorupon instantiation of your object, IteratorTest. You then add some data to the ArrayList, arr.

您正在定义Iterator对象的实例化IteratorTest. 然后,一些数据添加到ArrayListarr

You have now modified your list, and thus the Iterator's state is invalid.

您现在已经修改了您的列表,因此Iterator的状态无效。

You cannot use the Iteratorand change the ArrayListwithout using the Iteratorto do it.

你不能使用Iterator,改变ArrayList不使用Iterator做到这一点。

回答by user7269274

Answer 4 is technically correct, but not because a for(;;)or "for each" loop is used instead of a while()loop. It simply a matter of the Iterator's declared scope within the Class rather than the method. First, let's look at the behavior of the two methods hasNext()and next():

答案 4 在技术上是正确的,但不是因为for(;;)使用了while()循环或“for each”循环而不是循环。它只是迭代器在类中声明的范围而不是方法的问题。首先,让我们看看这两种方法的行为hasNext()next()

The hasNext()method simply queries an internal cursor (index); next()actually advances the cursor, therefore that is the "modification" that could raise the exception. If you try to use an Iterator declared and assigned outside of the method in which next()is being used, the code will throw an exception on the first next(), regardless if it's a for(;;)or while().

hasNext()方法只是查询一个内部游标(索引);next()实际上推进光标,因此这是可能引发异常的“修改”。如果您尝试使用在next()正在使用的方法之外声明和分配的迭代器,则代码将在第一个上抛出异常next(),无论它是 afor(;;)还是while()

In Answer 4 and 8, the iterator is declared and consumed locally within the method. It just so happens that since the for(;;)construct allows for a first time declaration and assignment of the iterator before the loop executes (which makes the iterator scoped to the for(;;)and implicitly within the method, making it "safe"). I agree that the for(;;)idiom is cleaner syntactically and fences scope at the lowest level of execution, completely within the for(;;)loop.

在答案 4 和 8 中,迭代器是在方法中本地声明和使用的。碰巧的是,由于该for(;;)构造允许在循环执行之前对迭代器进行第一次声明和赋值(这使得迭代器的范围限定为for(;;)和 隐式在方法中,使其“安全”)。我同意这个for(;;)习语在句法上更清晰,并且在最低执行级别将范围围起来,完全在for(;;)循环内。

Answer 8 is correct, because the Iterator is assigned and used locally inside the method.

答案 8 是正确的,因为 Iterator 是在方法内部本地分配和使用的。

But, just for sake of the discussion, the following method using a while()statement is syntactically correct, "safe" and non-modifying from a scope and reference perspective:

但是,为了讨论起见,以下使用while()语句的方法在语法上是正确的、“安全的”并且从范围和引用的角度来看是不可修改的:

somewhere in the Class definition ...

类定义中的某处...

ArrayList<String> messageList;

somewhere in the class constructor

在类构造函数中的某处

messageList = new ArrayList<String>(); 

add a method...

添加方法...

public printMessages ( )
{

  Iterator<String> messageIterator = messageList.iterator();

  while (messageIterator.hasNext())
     {
     System.out.println(messageIterator.next());
     }

  System.out.flush();

}