Java 为什么我会得到ConcurrentModificationException?

Java 为什么我会得到ConcurrentModificationException?,java,linked-list,priority-queue,Java,Linked List,Priority Queue,为什么要在代码中的指定位置获取ConcurrentModificationException?我不知道我做错了什么。。。正在使用removeMin()方法在列表pq中查找最小值,将其删除并返回其值 import java.util.Iterator; import java.util.LinkedList; public class test1 { static LinkedList<Integer> list = new LinkedList<Integer>

为什么要在代码中的指定位置获取ConcurrentModificationException?我不知道我做错了什么。。。正在使用
removeMin()
方法在列表
pq
中查找最小值,将其删除并返回其值

import java.util.Iterator;
import java.util.LinkedList;

public class test1 {

    static LinkedList<Integer> list = new LinkedList<Integer>();

    public static void main(String[] args) {
        list.add(10);
        list.add(4);
        list.add(12);
        list.add(3);
        list.add(7);

        System.out.println(removeMin());
    }

    public static Integer removeMin() {
        LinkedList<Integer> pq = new LinkedList<Integer>();
        Iterator<Integer> itPQ = pq.iterator();

        // Put contents of list into pq
        for (int i = 0; i < list.size(); i++) {
            pq.add(list.removeFirst());
        }

        int min = Integer.MAX_VALUE;
        int pos = 0;
        int remPos = 0;

        while (itPQ.hasNext()) {
            Integer element = itPQ.next(); // I get ConcurrentModificationException here
            if (element < min) {
                min = element;
                remPos = pos;
            }
            pos++;
        }

        pq.remove(remPos);
        return remPos;
    }

}
import java.util.Iterator;
导入java.util.LinkedList;
公共类test1{
静态LinkedList=新建LinkedList();
公共静态void main(字符串[]args){
增加(10);
增加(4);
增加(12);
增加(3);
增加(7);
System.out.println(removeMin());
}
公共静态整数removeMin(){
LinkedList pq=新建LinkedList();
迭代器itPQ=pq.Iterator();
//将列表内容放入pq
对于(int i=0;i
您面临一个问题,因为您在为
pq
创建迭代器之后,使用正常的
.add()
方法向
pq
添加了项。迭代器在执行
hasNext()
时不会抱怨,因为它在
pq
中看到了变化

while (itPQ.hasNext()) {
    ...
    Integer element = itPQ.next(); --> you get exception here
    ...
}


但是,当您尝试遍历
pq
时,它会引发异常。根据这一点,“如果迭代器检测到某些修改没有使用其方法(或在同一集合上使用另一个迭代器),它无法再保证它不会在同一个元素上传递两次或跳过一次,因此它会抛出此异常。”

您面临一个问题,因为您将项添加到了
pq
,在为
pq
创建迭代器之后,使用普通的
.add()
方法。迭代器在执行
hasNext()
时不会抱怨,因为它在
pq
中看到了变化

while (itPQ.hasNext()) {
    ...
    Integer element = itPQ.next(); --> you get exception here
    ...
}


但是,当您尝试遍历
pq
时,它会引发异常。根据这一点,“如果迭代器检测到某些修改没有使用其方法(或在同一集合上使用另一个迭代器),它就不能再保证它不会在同一个元素上传递两次或跳过一次,因此它会抛出此异常。”

我运行了您的代码,事实证明,这里的底线是:

Iterator<Integer> itPQ = pq.iterator();
Iterator itPQ=pq.Iterator();
这需要在填充
pq
之后进行,以便迭代器不会异步更新其数据

通过此修改,代码将运行



现在,它的运行不正常。原因正如@Ishnark在他的回答中指出的,每次你从列表中删除时,它都会变小,因此并非所有的列表都会被添加到
pq
我运行了你的代码,结果发现有问题的行在这里:

while (itPQ.hasNext()) {
    ...
    Integer element = itPQ.next(); --> you get exception here
    ...
Iterator<Integer> itPQ = pq.iterator();
Iterator itPQ=pq.Iterator();
这需要在填充
pq
之后进行,以便迭代器不会异步更新其数据

通过此修改,代码将运行



现在,它的运行不正常。原因是@Ishnak在他的回答中指出,每次从列表中删除时,它都会变小,因此并非所有列表都被添加到
pq

一旦从中获取迭代器的集合被修改,迭代器就不应被视为可用。(对java.util.concurrent.*集合类放宽了此限制。)

while (itPQ.hasNext()) {
    ...
    Integer element = itPQ.next(); --> you get exception here
    ...
首先为
pq
获取迭代器,然后修改
pq
。一旦修改
pq
,迭代器
itPQ
就不再有效,因此当您尝试使用它时,会出现ConcurrentModificationException

一种解决方案是移动迭代器itPQ=pq.Iterator()
while
循环之前的右侧。更好的方法是完全取消迭代器的显式使用:

for (Integer element : pq) {

从技术上讲,for-each循环在内部使用迭代器,因此无论哪种方式,只要您不尝试在循环内部修改
pq
,此循环都将有效。

迭代器在从中获取的集合被修改后,不应被视为可用。(对java.util.concurrent.*集合类放宽了此限制。)

首先为
pq
获取迭代器,然后修改
pq
。一旦修改
pq
,迭代器
itPQ
就不再有效,因此当您尝试使用它时,会出现ConcurrentModificationException

一种解决方案是移动迭代器itPQ=pq.Iterator()
while
循环之前的右侧。更好的方法是完全取消迭代器的显式使用:

for (Integer element : pq) {

从技术上讲,for-each循环在内部使用迭代器,因此无论哪种方式,只要不尝试在循环内部修改
pq
,该循环都是有效的。

我的猜测是,由于您在开始添加额外元素之前创建了
Iterator
,迭代器的脚下突然更新了数据,因此,我的猜测是,由于您在开始添加额外元素之前创建了
迭代器
,迭代器的脚下突然更新了它的数据,因此,虽然我同意这绝对是粗略的代码,但OP明确指出,错误不会在此处抛出,这与
列表
无关。异常是由于获取
itPQ
,然后修改
pq
,然后尝试使用
itPQ