Java中遍历时安全删除集合元素的唯一可靠方式是Iterator.remove();因for-each和普通for循环分别会触发ConcurrentModificationException或跳过元素,而Iterator.remove()严格要求紧跟next()调用,同步更新modCount以避免fail-fast异常。

用 Iterator 遍历集合比普通 for 循环更安全、更灵活,尤其适合边遍历边删除元素的场景。普通 for 循环直接操作索引,在 ArrayList 中可能因结构变化导致 ConcurrentModificationException 或漏删;而 Iterator 提供了线程安全(单线程下)的 remove() 方法,是唯一推荐的遍历中删除方式。
为什么要用 Iterator 而不是 for(int i=0;...)
普通 for 循环依赖下标,但集合在遍历时被修改(如 list.remove(i)),后续元素会前移,导致跳过下一个元素。例如:
list = ["a", "b", "c", "d"]
for (int i = 0; i < list.size(); i++) {
if ("c".equals(list.get(i))) list.remove(i); // 删除后 "d" 移到索引 2,但 i 变成 3,跳过了 "d"
}
-
Iterator的next()和remove()是配对设计,内部维护游标位置,删除不会影响后续遍历逻辑 - 所有
Collection子类都支持iterator(),写法统一,不依赖是否实现RandomAccess - 增强 for 循环(
for (E e : list))底层就是用Iterator,但它不暴露remove(),无法安全删除
标准 Iterator 遍历写法(含安全删除)
核心三步:获取迭代器 → 检查是否有下一元素 → 获取并处理元素。删除必须紧跟在 next() 之后、且只能调用一次 remove():
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String item = it.next();
if ("target".equals(item)) {
it.remove(); // ✅ 唯一安全的删除方式
}
}
- 不能在没调用
next()时调用remove(),会抛IllegalStateException - 不能连续两次调用
remove(),否则也抛异常 - 若只需遍历不修改,用增强 for 更简洁;若需删除,必须显式用
Iterator
替代方案对比:forEach + removeIf(Java 8+)
如果只是按条件删除,Collection.removeIf() 更简洁且内部仍用 Iterator:
立即学习“Java免费学习笔记(深入)”;
list.removeIf("target"::equals); // 等价于上面的 while + it.remove()
- 语义清晰,一行解决过滤删除
- 底层仍是
Iterator实现,同样安全 - 但无法在删除过程中做其他操作(比如记录日志、更新关联数据),这时还是得用原始
Iterator写法
注意点:并发修改异常与 fail-fast 机制
Iterator 默认是 fail-fast 的——如果遍历中集合被外部线程或本线程其他代码直接修改(如 list.add()),会立即抛 ConcurrentModificationException:
Iterator<String> it = list.iterator();
list.add("new"); // ⚠️ 这里触发 modCount 检查
it.next(); // 抛异常
- 这是设计上的保护机制,提醒你避免非预期的并发修改
- 真需要并发遍历,应改用线程安全集合(如
CopyOnWriteArrayList)或加锁 - 不要依赖 catch 这个异常来控制流程,它不是业务逻辑的一部分


















