java中ArrayList的遍历删除元素(二)
事件起因:
有如下一个ArrayList,需要删除其中字符串有 "2" 的元素
博主当时使用了foreach循环,即如下代码
结果现实狠狠的给了我一巴掌,代码执行报错
查询经过:
然后查看源码后,发现是如下代码抛出异常
在 next 方法中调用的 checkForComodification 方法中
当 modCount != expectedModCount 就会抛出该异常
这里有个疑问就是代码中没有调用next方法,但是这里却执行了next方法,是因为虚拟机执行的是编译后的代码,所以看一下编译后代码
从上述代码中可以看出,foreach循环编译后变成了迭代器循环,此处执行了next方法
继续翻看源码,发现expectedModCount 是迭代器初始化时使用的计数器,保证迭代器预期list中的应该有的元素数量,若发生了 modCount != expectedModCount 则认为发生了并发修改
正确处理:
使用迭代器删除方法
翻看迭代器remove方法源码,可以发现,在调用list删除元素方法后,再次更正了expectedModCount 的值,所以不会产生上述错误
拓展:
单线程执行上述代码无问题,但是多线程执行会产生并发异常
多线程一般会对迭代器资源上锁,或者使用并发容器