一.问题:
在我们的日常开发中,可能偶尔也会遇到需要在循环里(新增或修改等操作),如果直接使用for循环遍历就会导致
异常报错:
java.util.ConcurrentModificationException: null
案例:
在官方文档中ConcurrentModificationException的介绍如下:
public class ConcurrentModificationException extends RuntimeException
当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
例如,某个线程在 Collection 上进行迭代时,通常不允许另一个线性修改该 Collection。通常在这些情况下,迭代的结果是不确定的。如果检测到这种行为,一些迭代器实现(包括 JRE 提供的所有通用 collection 实现)可能选择抛出此异常。
ConcurrentModificationException是Java中很常见的一种异常,尤其是使用集合类的时候,很容易出现。
二:原因:
在新增操作以后,集合的expectedModCount和modCount的值不一致,这两个变量的作用都是记录修改次数的。二者不相等,所以会抛错。
在ArrayList源码实现中有个判断校验
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
从这段代码可以看出返回的是一个指向Itr类型对象的引用,我们接着看Itr的具体实现,在ArrayList类中找到了Itr类的具体实现,它是ArrayList的一个成员内部类,下面这段代码是Itr类的所有实现:
里面的几个成员变量:
- cursor:表示下一个要访问的元素的索引,从next()方法的具体实现就可看出
- lastRet:表示上一个访问的元素的索引
- expectedModCount:表示对ArrayList修改次数的期望值,它的初始值为modCount。
- modCount是AbstractList类中的一个成员变量
/**
* An optimized version of AbstractList.Itr
*/
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
三.解决
可以使用索引遍历(普通for循环)就可以解决,如下
看完恭喜你,又知道了一点点!!!
你知道的越多,不知道的越多!
~感谢志同道合的你阅读, 你的支持是我学习的最大动力 ! 加油 ,陌生人一起努力,共勉!!
注: 如果本篇有需要改进的地方或错误,欢迎大神们指定一二~~