Java 为什么我会得到ConcurrentModificationException?
为什么要在代码中的指定位置获取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>
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
。