Java中安全删除集合元素必须调用Iterator.remove()且仅在next()后立即执行,因fail-fast机制通过modCount和expectedModCount校验一致性,直接调list.remove()会触发ConcurrentModificationException。

Java 中在使用 Iterator 遍历时安全删除集合元素,核心就一条:必须调用 Iterator.remove(),且只能在调用 next() 之后立即执行。这是唯一被 JVM fail-fast 机制允许的删除方式。
为什么不能直接用 list.remove()
ArrayList、LinkedList 等集合的迭代器是 fail-fast 的:内部通过 modCount(集合修改计数)和 expectedModCount(迭代器预期值)做一致性校验。直接调 list.remove() 会改变 modCount,但迭代器不知道,下次 next() 就抛 ConcurrentModificationException。增强 for 循环本质也是 Iterator,同样不支持删除。
正确写法:三步节奏不能乱
- 先获取迭代器:
Iterator<string> it = list.iterator();</string> - 用
while (it.hasNext())控制循环,确保不越界 - 每次循环中只调一次
it.next()取出当前元素 - 在
next()之后、下一次next()之前,按需调it.remove()
常见错误要避开
- 还没调
next()就调remove()→ 抛IllegalStateException - 同一个
next()后连续调两次remove()→ 同样抛IllegalStateException - 混用
it.remove()和list.remove()→ 仍可能触发并发修改异常 - 在多线程下共享同一 Iterator → 即使只用
remove()也不安全,需额外同步
更简洁的替代方案(Java 8+)
如果只是按条件批量删除,list.removeIf(predicate) 更干净:
在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。
list.removeIf(s -> s == null || s.trim().isEmpty());
立即学习“Java免费学习笔记(深入)”;
它底层仍用 Iterator 实现,自动处理状态同步,但不支持中途 break 或复杂副作用操作。

















