java.util.ConcurrentModificationException异常分析
java.util.ConcurrentModificationException
原因:迭代器遍历过程中,调用了集合的remove操作。
复现:
List<Integer> list = new LinkedList<>();
list.add(1);
list.add(2);
list.add(3);
Iterator<Integer> iterator = list.iterator();
for (Integer n: list) {
list.remove(n);
}
抛出异常:
java.util.ConcurrentModificationException
异常原因:LinkedList 的remove方法只会修改modCount的值而不修改expectedModCount的值
Iterator<Integer> iterator = list.iterator();
这条语句,其实是创建了一个ListItr的对象,ListItr是LinkedList的一个内部类,定义如下:
private class ListItr implements ListIterator<E> {
private Node<E> lastReturned;
private Node<E> next;
private int nextIndex;
private int expectedModCount = modCount;
//注:内部类方法可以访问该类定义所在的作用域中的数据
其中,modCount是LinkedList继承自祖先类AbstractList的属性,表示LinkedList被结构修改的次数,结构修改可以简单地理解为改变链表大小的操作,expectedModCount 为期望值。
当执行LinkedList的remove操作时,LinkedList的remove方法只会修改modCount的值,而不会修改expectedModCount 的值,在遍历下一个元素时,调用next()方法,会对modCount和expectedModCount进行比较,如果不相等,抛出并发修改异常,即java.util.ConcurrentModificationException。
public E next() {
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
迭代器的remove等方法
迭代器的remove方法会修改modCount和expectedModCount,以下代码正常运行
List<Integer> list = new LinkedList<>();
list.add(1);
list.add(2);
list.add(3);
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){
iterator.next();
iterator.remove();
}
对 next 方法和 remove 方法的调用具有互相依赖性。如果调用 remove 之前没有调用 next 将是不合法的。如果这样做, 将会抛出一个 IllegalStateException 异常。