前言
在对一个list进行循环,将其中一些元素从list中移除时:
在此之前先弄清楚一些相关的知识。
Fail-Fast机制
快速失败也就是fail-fast,它是Java集合的一种错误检测机制。
java.util包中的集合类都有 fail-fast 检测,如果fail-fast迭代器检测到在迭代过程中进行了更改操作,那么它会抛出 ConcurrentModificationException。
Fail-Safe机制
java.util.concurrent中的集合类都为fail-safe的,不会抛出ConcurrentModificationException异常
modCount
在java.util的集合类中,都包含这个属性
HashMap源码:
AbstractList源码:
表示集合结构上被修改的次数。(所有涉及结构变化的方法中,都增加了modCount的值)
下面举例ArrayList中部分函数源码:
添加:
移除:
清空:
ConcurrentModificationException抛出
在集合内部迭代类中,还会有一个属性expectedModcount
ArrayList:
HashMap:
初始值都是等于modCount。
在内部迭代时涉及结构变化的方法中,都会判断expectedModCount是否等于modCount
解决方法
单线程情况:
(1)使用Iterator提供的remove方法,用于删除当前元素。
(2)建立一个集合,记录需要删除的元素,之后统一删除。
(3)不使用Iterator进行遍历,需要之一的是自己保证索引正常。
(4)使用并发集合类来避免ConcurrentModificationException,比如使用CopyOnArrayList,而不是ArrayList。
多线程情况:
(1)使用并发集合类,如使用ConcurrentHashMap或者CopyOnWriteArrayList。