10

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

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

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

4

8 回答 8

21

这是因为您在执行完之后继续遍历列表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()来检查是否有下一个元素可用。

于 2013-03-13T11:52:18.017 回答
2

foreach构造使用底层Iterator.

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

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

于 2013-03-13T11:53:45.270 回答
1

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

直接使用迭代器:

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

        if (studentName.equalsIgnoreCase(student.getName())) {
                it.remove();
                return true;
        }
    }
    return false;
于 2013-03-13T11:53:26.103 回答
1

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

于 2014-07-22T07:31:16.363 回答
0

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

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

于 2013-03-13T11:54:41.913 回答
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
    }
}
于 2013-03-13T11:53:16.710 回答
0
于 2013-03-13T11:53:16.907 回答
0

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

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;
}
于 2013-03-13T11:53:24.480 回答