Java中安全删除集合元素的唯一可靠方式是Iterator.remove(),因for-each和普通for循环分别会触发ConcurrentModificationException或跳过元素;removeIf()是Java 8+推荐的简洁替代,但不支持副作用操作;多线程下仍需线程安全集合。

Java 中遍历时安全删除集合元素,唯一可靠的方式是用 Iterator.remove(),而不是调用集合自身的 remove() 方法。这是因为 Java 集合的迭代器采用 fail-fast 机制,一旦检测到结构被意外修改,就会抛出 ConcurrentModificationException。
为什么不能在 for-each 或普通 for 循环里删元素
增强 for 循环(for (String s : list))本质就是 Iterator 的语法糖,但它隐藏了迭代器对象,你无法调用 it.remove();如果在循环体中写 list.remove(s),会直接触发异常。
普通正向 for 循环(for (int i = 0; i < list.size(); i++))虽不抛异常,但删除后元素前移,而索引仍自增,导致跳过下一个元素——例如删掉索引 1 的项,原索引 2 的元素移到 1,但 i 已变成 2,这个元素就被漏掉了。
Iterator.remove() 的正确用法
必须严格遵循“先 next → 再判断 → 满足条件就 remove”的节奏,且每次 next() 最多对应一次 remove():
立即学习“Java免费学习笔记(深入)”;
- 调用
collection.iterator()获取迭代器 - 用
while (it.hasNext())控制循环 - 每次循环内必须先执行
it.next()取出当前元素 - 仅在刚调完
next()后、且尚未再次调next()前,才能调it.remove() - 重复调
remove()(中间没next())或未调next()就调remove(),都会抛IllegalStateException
更简洁的替代方案:removeIf()
Java 8+ 提供了 Collection.removeIf(Predicate),底层仍是封装好的 Iterator.remove(),语义清晰、代码简短,推荐用于简单条件过滤:
list.removeIf(s -> s.length() > 5);
注意它不适用于需要在删除前记录日志、统计、或执行副作用操作的场景;也不支持获取被删元素本身。
多线程环境下仍不安全
即使用了 Iterator.remove(),若其他线程同时修改同一集合(如另一线程调 add()),仍可能抛 ConcurrentModificationException。这不是 bug,而是 fail-fast 的设计意图——它只保障单线程下的结构一致性。
并发场景应选用线程安全集合:CopyOnWriteArrayList(读多写少)、Collections.synchronizedList()(需手动同步块)、或 ConcurrentHashMap(注意其 keySet 迭代器不支持 remove())。


















