java Java并发修改异常错误

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

Java Concurrent Modification Exception Error

javaarraylist

提问by ToniHopkins

Im playing around with some code for my college course and changed a method from

我在为我的大学课程玩一些代码并改变了一个方法

public boolean removeStudent(String studentName)
{
    int index = 0;
    for (Student student : students)
    {
        if (studentName.equalsIgnoreCasee(student.getName()))
        {
            students.remove(index);
            return true;
        }
        index++;
    }
    return false;
}

To:

到:

public void removeStudent(String studentName) throws StudentNotFoundException
{
    int index = 0;
    for (Student student : students)
    {
        if (studentName.equalsIgnoreCase(student.getName()))
        {
            students.remove(index);
        }
        index++;
    }
    throw new  StudentNotFoundException( "No such student " + studentName);
}

But the new method keeps giving a Concurrent Modification error. How can I get round this and why is it happening?

但是新方法不断给出并发修改错误。我怎样才能解决这个问题,为什么会这样?

回答by Zutty

It is because you continue traversing the list after performing remove().

这是因为你在执行之后继续遍历列表remove()

You're reading and writing to the list at the same time, which breaks the contract of the iterator underlying the foreach loop.

您同时读取和写入列表,这破坏了 foreach 循环底层迭代器的约定。

Use Iterator.remove()

利用 Iterator.remove()

for(Iterator<Student> iter = students.iterator(); iter.hasNext(); ) {
    Student student = iter.next();
    if(studentName.equalsIgnoreCase(student.getName()) {
        iter.remove();
    }
}

It is described as the following:

它的描述如下:

Returns the next element in the iteration.

Throws NoSuchElementExceptionif the iteration has no more elements.

返回迭代中的下一个元素。

NoSuchElementException如果迭代没有更多元素,则抛出。

You can use Iterator.hasNext()to check if there is a next element available.

您可以使用Iterator.hasNext()来检查是否有可用的下一个元素。

回答by hthserhs

foreachconstruct uses an underlying Iterator.

foreach构造使用底层Iterator.

In the second method you continue to iterate even after removing an item from the list. This is resulting in the exception that you see. Take a look at this statement taken from ConcurrentModificationExceptiondocumentation:

在第二种方法中,即使从列表中删除项目后,您仍继续迭代。这导致您看到的异常。看一下取自ConcurrentModificationException文档的声明:

For example, it is not generally permissible for one thread to modify a Collection while another thread is iterating over it. In general, the results of the iteration are undefined under these circumstances. Some Iterator implementations (including those of all the general purpose collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected.

例如,通常不允许一个线程修改一个集合,而另一个线程正在对其进行迭代。通常,在这些情况下迭代的结果是不确定的。如果检测到此行为,某些迭代器实现(包括 JRE 提供的所有通用集合实现的实现)可能会选择抛出此异常。

回答by omer schleifer

You shouldn't delete objects from a collection while using a for-each statement - this will cause exceptions as your iterator faces a changed collection in the course of its iterations. (the for loop) either use a regular for loop (for int i = 0; i < 100; i++) etc... or keep the objects to remove in a list, and remove them outside of the for loop.

使用 for-each 语句时不应从集合中删除对象 - 这将导致异常,因为您的迭代器在迭代过程中面临更改的集合。(for 循环)要么使用常规的 for 循环(for int i = 0; i < 100; i++)等...要么将要删除的对象保留在列表中,并将它们删除到 for 循环之外。

Also, you remove the object by index where index is : 0 , 1 , 2 but index should actaully be the index of the student.

此外,您通过索引删除对象,其中索引是: 0 , 1 , 2 但索引实际上应该是学生的索引。

回答by Ker p pag

you can avoid concurrent modification error buy just breaking the loop after removing the element or if the method has a return type return a value after removing the element.

您可以避免并发修改错误,只需在删除元素后中断循环,或者如果该方法具有返回类型,则在删除元素后返回一个值。

回答by mmoore

This error occurs because you are trying to alter the size of a collection while you are iterating it. If you have 10 students, you start your loop expecting to go through 10 iterations. When you remove a student, how many iterations do still need to go? The answer obviously depends on where you removed your student from the list and where you currently are in your iteation. Obviously, java cannot know this.

出现此错误是因为您在迭代集合时试图更改集合的大小。如果您有 10 名学生,则您开始循环并期望经过 10 次迭代。当您删除一个学生时,还需要进行多少次迭代?答案显然取决于您将学生从列表中删除的位置以及您当前所在的位置。显然,java无法知道这一点。

To get around this, you must use an iterator. You can accomplish this as follows:

为了解决这个问题,您必须使用迭代器。您可以按如下方式完成此操作:

Iterator<Student> studentsIterator;
for(studentsIterator = students.iterator(); studentsIterator.hasNext();)
{
    Student student = studentsIterator.next();
    if(student... /* condition */)
    {
        studentIterator.remove();  //This removes student from the collection safely
    }
}

回答by Nikolay Kuznetsov

You are not allowed to removean element from studentscollection while iterating through it.

迭代时不允许从集合中删除元素students

This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.

For example, it is not generally permissible for one thread to modify a Collection while another thread is iterating over it. In general, the results of the iteration are undefined under these circumstances.

当不允许此类修改时,检测到对象的并发修改的方法可能会抛出此异常。

例如,通常不允许一个线程修改一个集合,而另一个线程正在对其进行迭代。通常,在这些情况下迭代的结果是不确定的。

http://docs.oracle.com/javase/6/docs/api/java/util/ConcurrentModificationException.html

http://docs.oracle.com/javase/6/docs/api/java/util/ConcurrentModificationException.html

Try changing to

尝试更改为

Iterator<Student> itr = students.iterator();
while (itr.hasNext()) {
    Student student = itr.next();
    if (studentName.equalsIgnoreCase(student.getName()))
    {
        itr.remove();
    }
}

回答by A4L

If you want to remove inside a loop you should use an iterator and its removemethod

如果要在循环内删除,则应使用迭代器及其remove方法

public boolean removeStudent(String studentName)
{
    Iterator<Student> itS = students.iterator();
    while(itS.hasNext())
    {
        Student student = itS.next();
        if (studentName.equalsIgnoreCasee(student.getName()))
        {
            itS.remove();
            return true;
        }
    }
    return false;
}

回答by Eyal Schneider

You are not allowed to remove an element from your collection while you iterate over it. The iterator detects a structural change during its usage, and throws the exception. Many collections are implemented in such a way.

迭代时不允许从集合中删除元素。迭代器在使用过程中检测到结构变化,并抛出异常。许多集合都是以这种方式实现的。

Use the iterator directly instead:

直接使用迭代器:

    Iterator<Student> it = students.iterator();
    while (it.hasNext()) {
        Student student = it.next();

        if (studentName.equalsIgnoreCase(student.getName())) {
                it.remove();
                return true;
        }
    }
    return false;