You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么增强for循环删除ArrayList元素“2”不抛出ConcurrentModificationException

现象原因分析

首先明确两个底层逻辑:

  • Java的增强for循环遍历集合本质是语法糖,底层依赖集合的Iterator迭代器实现遍历
  • ArrayList的迭代器内部维护3个核心变量:
    • modCount:集合本身的修改次数,每次add/remove操作都会自增
    • expectedModCount:迭代器初始化时拷贝的modCount值,遍历过程中如果和modCount不一致就会触发ConcurrentModificationException
    • cursor:下一个待遍历元素的索引,初始为0,每调用一次next()方法就自增1,hasNext()方法的判断逻辑为return cursor != size;

对应代码的执行过程拆解

集合初始化后共有3个元素,size=3,元素按顺序为"1"、"2"、"3",对应索引为0、1、2:

  1. 迭代器初始化:expectedModCount = modCount = 3,cursor=0
  2. 第一次遍历:hasNext()判断0 != 3返回true,调用next()返回索引0的"1",cursor变为1,校验expectedModCount和modCount一致,无异常,不满足删除条件,继续遍历
  3. 第二次遍历:hasNext()判断1 !=3返回true,调用next()返回索引1的"2",cursor变为2,校验一致,无异常。匹配删除条件后调用list.remove("2"),此时集合size变为2,modCount自增为4,迭代器的expectedModCount仍为3,cursor保持为2
  4. 第三次遍历前先调用hasNext():判断cursor=2是否等于当前集合size=2,结果为true,直接返回false,循环终止,不会调用next()方法,也就不会触发expectedModCount和modCount的一致性校验,因此不会抛出异常。

注意:这是非常偶然的边界情况,只有删除倒数第二个元素时才会触发,删除其他位置的元素都会因为后续还会调用next()触发校验抛出异常,千万不要把这种巧合当成规范写法,遍历中删除元素一定要使用迭代器自带的remove()方法,或者使用Stream的filter方法生成新集合。

内容的提问来源于stack exchange,提问作者Daiqing Yang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 03:45:03