java集合迭代失效机制的核心在于modcount、expectedmodcount与checkforcomodification()的协同校验:创建迭代器时快照modcount,每次next()前比对二者,list.remove()使modcount自增而expectedmodcount未更新,导致下一次next()抛concurrentmodificationexception。

Java 集合迭代失效机制的核心,不在“失效”本身,而在“谁改了结构、何时被发现、为什么必须这样设计”。用一道经典错题切入,最能剥开层层封装,看清 modCount、expectedModCount 和 checkForComodification() 三者之间的逻辑咬合。
典型错误代码:增强 for 循环中直接 remove
这段代码几乎每个 Java 初学者都写过:
Listfor (String s : list) {
if ("B".equals(s)) {
list.remove(s); // ⚠️ 错误:用集合自身方法删除
}
}
运行时抛出 ConcurrentModificationException。这不是多线程问题,而是单线程下的结构不一致检测——增强 for 底层自动展开为 Iterator,而 list.remove() 修改了 modCount,但迭代器内部的 expectedModCount 没同步更新。
关键三步还原:从创建到崩溃
- 创建迭代器时快照 modCount:调用 iterator() 时,Itr 构造器将当前 list.modCount(比如是 3)赋给 expectedModCount;此时两者相等
- next() 前强制校验:每次调用 next(),第一件事就是执行 checkForComodification(),比对 modCount 与 expectedModCount
- remove() 破坏一致性:list.remove() 内部使 modCount++(变为 4),但 expectedModCount 仍为 3 → 下一次 next() 触发异常
正确做法:只用迭代器自己的 remove()
必须在调用过 next() 后,立刻用同一个迭代器对象的 remove() 方法:
Iteratorwhile (it.hasNext()) {
String s = it.next();
if ("B".equals(s)) {
it.remove(); // ✅ 安全:它会同步更新 expectedModCount
}
}
因为 Iterator.remove() 不仅调用底层集合的删除逻辑,还会把 expectedModCount 重置为当前 modCount,维持二者一致。
不是所有容器都“一删就崩”
- ArrayList / Vector(连续内存):删除元素导致后续元素前移,下标错位 + modCount 不匹配 → 必然 fail-fast
- LinkedList(链表):删除节点只影响前后指针,但依然维护 modCount,同样触发快速失败(逻辑一致,非结构原因)
- CopyOnWriteArrayList:写时复制,迭代器基于快照,即使原集合被修改也不会抛异常 —— 这是唯一绕过 fail-fast 的标准集合,但代价是内存和写性能
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











