为什么我会收到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 itPQ = pq.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。 根据这篇文章 , “如果迭代器检测到某些修改没有使用它的方法(或在同一个集合上使用另一个迭代器),它就不能再保证它不会在同一个元素上传递两次或跳过一个,所以它抛出这个例外。“