选自《阿里巴巴JAVA开发手册》
图1代码执行情况是:解释删除1这个元素不会报错,但是删除2这个元素报错了,这个情况如何解释?
从报的错误中可以知道错误的来源
checkForComodification()
,如果要避免错误需要保持
modCount != expectedModCount
为
false
。
list.remove(Object)
会去调用
fastRemove(int)
方法,这个时候必然会去修改
modCount
,这个时候就会出现错误。
Iterator<String> iterator = list.iterator()
;这个方法的实现就是返回一个内部类
Itr
,(迭代的过程都是使用的这个类),但是为什么这个
iterator.remove()
不会出现错误了,原因在与这个方法的实现是在进行实际的
ArrayList.this.remove
之前进行的
checkForComodfication
检查,
remove
之后又使
expectedModCount = modCount
,所以不会出现错误。
Itr.remove
的实现
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();
}
}
如果有不对的地方请指出 @叉叉哥 @蒲柳隐逸
单线程的情况下,在遍历List时删除元素,必须要用Iterator的remove方法而不能使用List的remove方法,否则会ConcurrentModificationException。试想如果一个老师正在点整个班级所有学生的人数,而学生如果不遵守纪律一会出去一会进来,老师肯定点不下去。
多线程的情况下,参考我的一篇博客:http://xxgblog.com/2016/04/02…
因为你在对元素进行增删的时候集合中的数量就改变了,那么在遍历的时候就有可能会出现问题.比如一个集合有10个元素,那就应该要遍历10次,当你对增加或删除了一个元素,遍历的次数就不对,所以会报错
倒序删除就可以了,反正list尽量不要remove。可以加delete标记
文档中那个黄色的说明很有意思。
这个例子的执行结果会出乎大家的意料,那么试下把“1”换成“2”,会是同样的结果吗?
这个还是要看
ArrayList
的源码,一看便知。
倒序删除就可以了
ArrayList不是线程安全的,这样相当于你在遍历的时候修改了List。
ArrayList在这种情况下是会抛出并发修改异常的。