症状
循环抛出 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。