Java中边遍历边删除ArrayList应使用Iterator的remove()方法、倒序for循环、收集后统一删除或removeIf(),禁用正序for或增强for直接remove,否则抛ConcurrentModificationException。

Java 中对 ArrayList 边遍历边删除,直接用普通 for 循环或增强 for 循环(foreach)调用 remove() 会抛出 ConcurrentModificationException(并发修改异常),因为 ArrayList 的迭代器是“快速失败”(fail-fast)的。关键是要用**安全的删除方式**,而不是“硬删”。
用 Iterator 的 remove() 方法(推荐)
这是最标准、最安全的方式。Iterator 提供了专用于遍历时删除的 remove() 方法,它会同步更新内部修改计数,避免异常。
示例:
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c", "b", "d"));
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if ("b".equals(s)) {
it.remove(); // ✅ 安全删除
}
}
// 结果:["a", "c", "d"]
注意:it.remove() 必须紧跟在 it.next() 之后调用,且只能调用一次;否则抛 IllegalStateException。
立即学习“Java免费学习笔记(深入)”;
倒序遍历 + 普通 for 循环
从索引 size()-1 往前遍历,删除元素不影响尚未访问的前面元素的索引,因此不会跳过或越界。
示例:
for (int i = list.size() - 1; i >= 0; i--) {
if ("b".equals(list.get(i))) {
list.remove(i); // ✅ 安全,因索引只减小,不干扰前面
}
}
优点:逻辑直观,适合按索引条件删除;缺点:不如 Iterator 语义清晰,且不能用于只读接口(如 Collection)。
收集待删元素,遍历结束后统一删除
先遍历一遍,把要删的对象(或索引)存进另一个集合,再调用 removeAll() 或逐个删。适用于删除逻辑复杂、或需多次判断的场景。
示例:
List<String> toRemove = new ArrayList<>();
for (String s : list) {
if ("b".equals(s)) {
toRemove.add(s);
}
}
list.removeAll(toRemove); // ✅ 安全,非遍历中操作
注意:removeAll() 时间复杂度为 O(n×m),大数据量时慎用;若元素重复,它会删掉所有匹配项(符合预期)。
使用 removeIf()(Java 8+,最简洁)
这是函数式写法,内部已封装了安全遍历逻辑,代码最简,语义最强。
示例:
list.removeIf(s -> "b".equals(s)); // ✅ 一行搞定,线程安全(单线程下)
底层其实也是基于 Iterator 实现,等价于第一种方式,但更易读、不易出错。推荐新项目优先使用。
不推荐的做法:用正序 for 循环配合 list.remove(i) —— 删除后后续元素前移,导致下标错位,漏删相邻元素。


















