Java并发修改异常错误

时间:2013-03-13 11:49:59

标签: java arraylist

我正在玩我的大学课程的一些代码并改变了

的方法
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;
}

要:

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);
}

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

8 个答案:

答案 0 :(得分:19)

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

你正在同时读取和写入列表,这打破了foreach循环下的迭代器的契约。

使用Iterator.remove()

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

描述如下:

  

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

     

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

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

答案 1 :(得分:1)

foreach构造使用基础Iterator

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

  

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

答案 2 :(得分:0)

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

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

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
    }
}

答案 3 :(得分:0)

在迭代它时,您不允许删除来自students集合的元素。

  

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

     

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

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

尝试更改为

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

答案 4 :(得分:0)

如果要在循环内删除,则应使用迭代器及其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;
}

答案 5 :(得分:0)

在迭代它时,不允许从集合中删除元素。迭代器在其使用期间检测结构更改,并抛出异常。许多集合都以这种方式实现。

直接使用迭代器:

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

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

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

你可以避免并发修改错误购买只是在删除元素后打破循环,或者如果方法有一个返回类型,则在删除元素后返回一个值。