← 中文资源

简体中文版本

Java 遍历集合时抛 ConcurrentModificationException

通过迭代器移除元素或使用并发集合,修复 ConcurrentModificationException。

阅读英文原文

症状

循环抛出 ConcurrentModificationException,有时出现在看似无并发的单线程代码里。名字有误导性:真正原因是迭代期间发生了结构修改,fail-fast 迭代器检测到便拒绝继续。在 for-each 中直接移除元素,或在子列表与流迭代时改动列表,都会触发它。

诊断

搜索循环内的 remove/add;改用 iterator.remove 或 removeIf;确认是否存在多线程共享。

grep -n "for (\|for (\(.*:\|remove(\|add(" src/*.java

根因

集合在迭代器活动期间被结构性修改,fail-fast 迭代器检测到后报告,而非带着不一致视图继续。

修复

通过 Iterator.remove 或 Collection.removeIf 移除,或在必须修改原集合时迭代防御性副本。若确有多线程访问,改用并发集合或同步整个迭代。

验证

重跑代码路径确认异常消失,再检查集合最终状态符合预期。若结果为空,说明修复移除了过多元素。

常见陷阱

在循环内用 list.remove 直删会破坏迭代器状态;应使用迭代器或 removeIf。