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

为何ListIterator.add不抛出ConcurrentModificationException而list.add会抛出?

为什么ListIterator的add操作不抛异常,直接调用List.add却会?

这个问题问到点子上了!其实核心原因在于ArrayList的fail-fast机制以及两种修改方式对迭代器状态的同步处理不同,我给你一步步讲清楚:

首先先把你的代码贴出来方便对照:

List<String> list = new ArrayList<String>();
list.add("hi");
list.add("whats up");
list.add("how are you");
list.add("bye");
ListIterator<String> i = list.listIterator();
while (i.hasNext()) {
    // 第7行:i.add("元素") → 不会报错
    // 第8行:list.add("元素") → 抛出ConcurrentModificationException
}

先搞懂ConcurrentModificationException为什么会出现

ArrayList内部维护了一个叫modCount的变量,用来记录集合被修改的次数(比如add、remove、clear这些操作都会让它自增)。当你通过list.listIterator()创建迭代器时,迭代器会把当前的modCount值存到自己的expectedModCount变量里。

在迭代过程中,每次调用hasNext()或者next()的时候,迭代器都会检查modCount和expectedModCount是否相等:如果不相等,就说明集合在迭代器不知情的情况下被修改了,这时候就会抛出ConcurrentModificationException——这就是所谓的fail-fast快速失败,用来提醒你迭代过程中不要随便修改集合。

直接调用list.add("元素")的问题

当你在循环里直接调用list.add()时,只会修改ArrayList的modCount(让它+1),但迭代器里的expectedModCount完全没变化。下一次循环执行i.hasNext()的时候,迭代器发现modCount != expectedModCount,立刻就抛出异常了。

ListIterator.add("元素")为什么安全?

ArrayList的ListIterator其实是它内部的ListItr类实现的,这个类重写了add方法,做了两个关键操作:

  1. 调用ArrayList的底层添加逻辑把元素加进去(这时候modCount会自增)
  2. 同步迭代器的expectedModCount,让它等于最新的modCount
  3. 调整迭代器的cursor(当前迭代位置),保证后续迭代能正确遍历新添加的元素

简单说,ListIterator的add方法是迭代器自己管理的修改操作,它知道集合被修改了,所以会同步自己的状态,让后续的迭代检查能通过,自然就不会抛出异常。

总结一下区别

  • 直接调用list.add():属于迭代器外部的修改,迭代器完全不知情,触发fail-fast检测,抛异常
  • 调用ListIterator.add():属于迭代器内部的安全修改,会同步迭代器和集合的状态,避免触发fail-fast检测

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:21:53