必须调用 Iterator 的 remove() 方法且仅在 next() 后立即执行;否则因 modCount 校验失败抛 ConcurrentModificationException。removeIf() 是 JDK8+ 安全替代,但不支持副作用操作。

Java 中在使用 Iterator 遍历时安全删除元素,核心就一条:**必须调用 Iterator 自身的 remove() 方法,且只能在刚调用过 next() 之后立即执行**。其他任何方式——比如在增强 for 循环里调 list.remove()、或在普通 for 循环中按索引删——都会导致异常或漏删。
为什么不能直接用集合的 remove()?
因为 ArrayList、LinkedList、HashSet 等集合内部维护一个 modCount(修改计数器),迭代器创建时会记录它的快照值(expectedModCount)。每次调 next() 前,迭代器都会校验两者是否一致。一旦你绕过迭代器、直接调集合的 remove(),modCount 就变了,但 expectedModCount 没更新,校验失败,立刻抛 ConcurrentModificationException——这不是多线程问题,单线程也会触发。
Iterator.remove() 的正确用法
这个方法是唯一被设计用于“边遍历边删”的安全入口,但它有严格时序要求:
- 必须先调一次
it.next(),拿到当前元素 - 紧接着在同一个循环体内,根据业务条件决定是否调
it.remove() - 每个
next()最多对应一次remove();重复调或没调next()就调,都会抛IllegalStateException
示例:
立即学习“Java免费学习笔记(深入)”;
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
List
Iterator
while (it.hasNext()) {
String s = it.next();
if ("bb".equals(s)) {
it.remove(); // ✅ 安全,紧跟 next()
}
}
// 结果:["a", "ccc"]
更简洁的替代方案:removeIf()
JDK 8+ 提供了语义更清晰的写法:
list.removeIf(s -> s.length() > 2); // ✅ 底层仍用 Iterator.remove(),自动处理细节
它适合纯条件过滤场景,代码短、不易错。但注意:
– 不支持在删除前做副作用操作(如打日志、统计、调外部服务)
– 无法获取被删的具体元素对象(若需,得先 stream().filter(...).collect() 再删)
常见误区和边界情况
-
增强 for 循环里删不了:它是语法糖,不暴露迭代器引用,
list.remove()必崩 -
正向 for 循环会漏删:删掉索引
i的元素后,后续元素前移,而i仍自增,导致跳过新位置上的元素 -
只读集合不支持:对
Collections.unmodifiableList()返回的集合调remove(),直接抛UnsupportedOperationException -
多线程下仍不安全:即使用了
it.remove(),其他线程同时修改集合,依然可能触发ConcurrentModificationException;高并发应选CopyOnWriteArrayList或加锁

















