Java中安全遍历集合需用Iterator.remove()而非集合自身的remove(),因快速失败机制会在结构性修改时抛ConcurrentModificationException;Java21前Iterator不支持添加,应暂存后批量添加或改用ListIterator。

Java 中使用 Iterator 安全遍历集合,核心是**避免在遍历过程中直接调用集合自身的 remove() 或 add() 方法**,而应始终通过 Iterator 提供的 remove()(和 Java 21+ 的 add())操作来修改集合。
为什么不能边遍历边用集合方法删元素?
大多数集合(如 ArrayList、HashSet)的迭代器是“快速失败”(fail-fast)的。一旦检测到集合结构被外部修改(比如调用 list.remove(obj)),下一次调用 iterator.next() 就会抛出 ConcurrentModificationException。这不是线程安全问题,而是单线程下结构性修改触发的校验机制。
正确做法:用 Iterator.remove() 删除当前元素
Iterator 的 remove() 方法是唯一被允许在遍历中安全删除当前元素的方式。它必须紧跟在 next() 之后调用,且每调用一次 next() 最多调用一次 remove()。
在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。
- ✅ 正确示例(删除所有偶数):
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
Integer num = it.next();
if (num % 2 == 0) {
it.remove(); // 安全!只删刚刚 next() 返回的那个
}
}
// 结果:[1, 3, 5]
遍历时添加元素?注意版本与限制
标准 Iterator 接口**不支持添加元素**(没有 add() 方法)。Java 21 引入了 ListIterator.add()(仅限 ListIterator),但普通 Iterator 仍不可添加。
立即学习“Java免费学习笔记(深入)”;
- ❌ 错误:在
while(it.hasNext())循环里调用list.add(x)→ 触发异常 - ✅ 替代方案:
- 收集待添加元素到另一个临时集合,遍历完再批量
addAll() - 若需插入到列表特定位置,改用
ListIterator(支持add()和set())
- 收集待添加元素到另一个临时集合,遍历完再批量
增强 for 循环本质也是 Iterator,同样不支持删除
for (String s : list) 是语法糖,底层仍使用 Iterator。因此在增强 for 中调用 list.remove() 同样会抛异常。
- ⚠️ 禁止写法:
for (String s : list) {
if (s.isEmpty()) {
list.remove(s); // ❌ 运行时抛 ConcurrentModificationException
}
}
- ✅ 正确写法:退回显式
Iterator并用it.remove()
其他安全提示
-
Iterator.remove()只能删除上一次next()返回的元素;重复调用或未调用next()就调用remove()会抛IllegalStateException - 多线程环境下,即使只用
Iterator.remove()也不保证线程安全,需额外同步(如用Collections.synchronizedList()或CopyOnWriteArrayList) - 对
ConcurrentHashMap、CopyOnWriteArrayList等并发集合,其迭代器通常弱一致性(weakly consistent),允许遍历时结构修改且不抛异常,但不保证反映最新状态

















