唯一安全方式是Iterator.remove();因for-each是Iterator语法糖但无法调用remove,普通for循环删会触发ConcurrentModificationException,倒序for、removeAll、ListIterator等为替代方案,多线程需CopyOnWriteArrayList或加锁。

Java 中在遍历集合时安全删除元素,唯一标准且可靠的方式是使用 Iterator.remove(),其他任何在循环中直接调用集合自身 remove() 的做法都会出问题。
为什么不能用 for-each 或普通 for 循环删
增强 for 循环(for (String s : list))本质就是 Iterator 的语法糖,但你拿不到迭代器对象,无法调 it.remove()。一旦在循环体里写 list.remove(s),集合的 modCount 就会和迭代器内部记录的 expectedModCount 对不上,立刻抛 ConcurrentModificationException。
普通正向 for 循环(for (int i = 0; i )虽然不抛异常,但删除后后续元素会前移,而 <code>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);
优点:安全、不易写错、可读性强。
限制:不支持获取被删元素本身(比如要记日志或做额外处理),也不适合需要复杂上下文逻辑的场景(如“删前两个匹配项后停止”)。
其他可行但需注意的方法
倒序 for 循环(for (int i = list.size() - 1; i >= 0; i--))可以避免索引错位,适合按索引删除;
先收集待删元素再批量调 list.removeAll(toRemove) 也行,但对 ArrayList 是 O(n×m) 复杂度,大数据量时不推荐;ListIterator 支持双向遍历和安全删除,适合需要反向操作的场景。
多线程环境下,即使用了 Iterator.remove() 也不安全,应改用 CopyOnWriteArrayList 或加锁。


















