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

为何这段ArrayList遍历删除代码会引发ConcurrentModificationError?

为什么遍历ArrayList时删除元素会触发ConcurrentModificationError?

首先得明确:你写的for (int e : l3)这种foreach循环,底层是靠**迭代器(Iterator)**实现的。ArrayList的迭代器有个核心校验机制,用来防止遍历过程中列表被“意外修改”,这就是你遇到错误的根源。

迭代器的核心校验逻辑

ArrayList内部维护了一个modCount变量,专门记录列表被修改(添加、删除元素)的总次数。当你创建迭代器时,它会把当前的modCount值复制到自己的expectedModCount变量里。

之后每次迭代器调用next()方法取下一个元素时,都会先做一件事:检查modCount和expectedModCount是否相等。如果不相等,就直接抛出ConcurrentModificationError——这就是所谓的“迭代器被干扰”,因为迭代器认为自己遍历的列表应该是“一成不变”的,一旦外部修改了列表,它就判定遍历环境被破坏了。

结合你的代码分析错误触发过程

看你的代码,初始列表是[0,2,3,5],modCount初始值是4(因为执行了4次add操作)。当foreach循环启动时,迭代器初始化,expectedModCount也被设为4。

接下来的执行步骤:

  1. 第一次循环:取出元素0,判断是偶数,调用l3.remove(i)(此时i=0)删除第一个元素。这时候ArrayList的modCount会自动加1,变成5,但迭代器的expectedModCount还是4。
  2. 迭代器准备取下一个元素,调用next()方法时,发现modCount != expectedModCount,直接抛出ConcurrentModificationError。

另外提一句:你的i++逻辑本身也有问题——就算没触发错误,删除元素后列表长度缩短,索引会错位,导致后续元素要么被重复处理,要么被跳过,但这是次要问题,核心错误还是迭代器的校验机制被触发了。

正确的做法:用迭代器自身的remove方法

如果要在遍历过程中删除元素,应该用迭代器自带的remove()方法,它会同步更新expectedModCount和modCount,避免校验失败:

List<Integer> l3 = new ArrayList<>();
l3.add(0); l3.add(2); l3.add(3); l3.add(5);

Iterator<Integer> iter = l3.iterator();
while (iter.hasNext()) {
    int e = iter.next();
    if (e % 2 == 0) {
        iter.remove();
    }
}

这样迭代器每次删除元素时,都会把自己的expectedModCount更新成当前的modCount,下次调用next()时校验就会通过。

内容的提问来源于stack exchange,提问作者Nadeem Hussain

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 08:12:15