为什么在for循环中删除元素时不总是抛出ConcurrentModificationException
三种遍历删除ArrayList元素结果差异的原因
首先明确核心基础原理:
ArrayList的fail-fast机制依赖两个核心变量:
modCount:记录集合结构修改的次数,add、remove等变更结构的操作都会让这个值+1expectedModCount:迭代器初始化时会把当前的modCount赋值给这个变量,每次调用迭代器的next()方法时都会校验两个值是否相等,不等就抛出ConcurrentModificationException
增强for循环的底层就是迭代器实现,普通for循环是自行通过索引访问,不涉及迭代器的校验逻辑。
场景1:普通for循环删除值为1的元素,输出[2,3]
普通for循环没有使用迭代器,不会触发modCount校验逻辑:
ArrayList<Integer> list = new ArrayList<Integer>(); list.add(1); list.add(2); list.add(3); for (int i = 0; i < list.size(); i++) { Integer integer = list.get(i); if (integer.equals(1)) { list.remove(integer); } } System.out.println(list);
执行逻辑:
- 初始size=3,i=0时拿到元素1,匹配删除后列表变为[2,3],size更新为2
- i自增到1,此时1 < 2,get(1)拿到元素3,不匹配删除条件
- 循环结束,最终输出[2,3]
注:普通for循环遍历删除存在元素漏判的隐患,比如要删除值为2的元素,删除后元素3会前移到索引1的位置,i自增到2就会直接结束循环,漏掉对元素3的校验
场景2:增强for循环删除值为1的元素,抛出ConcurrentModificationException
增强for循环底层走迭代器逻辑,会触发校验:
for (Integer integer : list) { if (integer.equals(1)) { list.remove(integer); } } System.out.println(list);
执行逻辑:
- 迭代器初始化时
expectedModCount = modCount = 3(三次add操作) - 第一次调用
next()拿到元素1,匹配删除条件,调用list.remove()会让modCount变为4,但expectedModCount还是3 - 下一轮循环先调用
hasNext(),此时cursor=1,size=2,cursor != size返回true,继续调用next(),此时校验发现modCount != expectedModCount,直接抛出异常
场景3:增强for循环删除值为2的元素,输出[1,3]
这是迭代器边界判断的特殊情况,没有触发校验逻辑:
for (Integer integer : list) { if (integer.equals(2)) { list.remove(integer); } } System.out.println(list);
执行逻辑:
- 迭代器初始化时
expectedModCount = modCount = 3 - 第一次调用
next()拿到元素1,不匹配,cursor变为1 - 第二次调用
next()拿到元素2,匹配删除条件,调用list.remove()后列表变为[1,3],size更新为2,modCount变为4,cursor变为2 - 下一轮循环调用
hasNext(),判断逻辑是cursor != size,此时cursor=2,size=2,返回false,循环直接结束,不会调用next(),也就不会触发modCount校验,所以不会抛异常,最终输出[1,3]
推荐的安全遍历删除方式
如果要避免异常,推荐两种标准写法:
- 显式使用迭代器的
remove()方法:
Iterator<Integer> iterator = list.iterator(); while (iterator.hasNext()) { Integer integer = iterator.next(); if (integer.equals(1)) { iterator.remove(); // 该方法会同步更新expectedModCount,避免校验不通过 } }
- Java 8及以上版本使用
removeIf()方法:
list.removeIf(integer -> integer.equals(1));
内容的提问来源于stack exchange,提问作者Huy Ha
相关产品推荐
相关产品推荐

