为什么我会收到ConcurrentModificationException?
为什么我在代码中的指定位置获得ConcurrentModificationException? 我无法弄清楚我做错了什么… removeMin()
方法用于定位列表中的min,删除它,并返回其值
import java.util.Iterator; import java.util.LinkedList; public class test1 { static LinkedList list = new LinkedList(); 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 pq = new LinkedList(); Iterator 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; } }
一旦获得迭代器的集合被修改,它就不应被视为可用。 (对java.util.concurrent。*集合类放宽了此限制。)
您首先获得pq
的Iterator,然后修改pq
。 修改pq
,Iterator itPQ
不再有效,因此当您尝试使用它时,会出现ConcurrentModificationException。
一种解决方案是移动Iterator
在while
循环之前。 更好的方法是完全废除Iterator的显式使用:
for (Integer element : pq) {
从技术上讲,for-each循环在内部使用Iterator,所以无论哪种方式,只要你不尝试修改循环中的pq
,这个循环才有效。
我运行了你的代码,事实certificate,违规行在这里:
Iterator itPQ = pq.iterator();
这需要在您的pq
填充之后 ,以便迭代器不会异步更新它的数据。
通过此修改,代码运行。
现在,它无法正常运行。 原因是@Ishnark在他的回答中指出,每次从列表中删除时,它都会变小,因此并非所有列表都被添加到pq
。
您遇到问题是因为在已经为pq
创建了Iterator之后使用普通的.add()
方法将项目添加到pq
。 当你执行hasNext()
时,迭代器不会抱怨,因为它看到了pq
的变化。
while (itPQ.hasNext()) { ... Integer element = itPQ.next(); --> you get exception here ...
}
但是,当您尝试遍历pq
时,它会抛出exception。 根据这篇文章 , “如果迭代器检测到某些修改没有使用它的方法(或在同一个集合上使用另一个迭代器),它就不能再保证它不会在同一个元素上传递两次或跳过一个,所以它抛出这个例外。“