推荐使用迭代器的remove()方法安全删除ArrayList元素,因其专为遍历中删除设计,避免ConcurrentModificationException;其次可选倒序for循环或先收集后批量删除,兼顾效率与安全性。

Java 中遍历 ArrayList 并安全删除元素,关键在于**避免并发修改异常(ConcurrentModificationException)和性能浪费**。直接用普通 for 循环配合 remove() 或增强 for 循环删除,极易出错或漏删。下面给出几种高效、安全、适用不同场景的方法。
✅ 推荐方式:使用迭代器(Iterator)的 remove()
这是最标准、线程安全(单线程下)、语义清晰的方式。迭代器的 remove() 方法专为边遍历边删除设计,不会触发 ConcurrentModificationException。
示例:删除所有偶数元素
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6));
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
Integer val = it.next();
if (val % 2 == 0) {
it.remove(); // ✅ 安全删除
}
}
// 结果:[1, 3, 5]
- 只能在调用
next()后立即调用一次remove() - 不能和集合自身的
remove()混用,否则仍会抛异常 - 时间复杂度 O(n),空间 O(1),适合大多数业务删除场景
✅ 批量删除:先收集索引/元素,再倒序 or 批量移除
若需根据复杂条件判断多个待删项(比如同时满足多个字段),可先遍历记录下标或引用,再统一删除——避免反复移动元素影响性能。
立即学习“Java免费学习笔记(深入)”;
-
倒序 for 循环删除索引:防止索引偏移
for (int i = list.size() - 1; i >= 0; i--) { if (shouldRemove(list.get(i))) list.remove(i); } -
收集待删对象,最后调用
removeAll():List<Integer> toRemove = new ArrayList<>();<br>for (Integer x : list) if (x < 0) toRemove.add(x);<br>list.removeAll(toRemove);
注意:removeAll内部是双重循环,对大列表较慢;但代码简洁,适合小数据或删除比例低的场景
⚠️ 避免踩坑:这些写法不安全或低效
-
增强 for 循环中调用
list.remove()→ 立即抛ConcurrentModificationException -
正序 for 循环中用
remove(i)→ 元素左移导致跳过下一个元素(如删掉索引 1 后,原索引 2 的元素移到 1,但循环已到 i=2) -
每次
remove()都触发数组复制 → 若频繁删除,建议改用LinkedList(仅当插入/删除远多于随机访问时) -
用
Stream.filter().collect()替换原列表 → 创建新列表,旧列表未释放,内存压力大;适合不可变处理,不适合“就地清理”
? 进阶提示:删除大量元素时考虑重构数据结构
如果业务中频繁执行「按条件过滤 + 删除」,且列表很大(如 > 10 万),可以:
- 改用
CopyOnWriteArrayList(仅适用于读多写极少、允许最终一致性的场景) - 用布尔标记字段 + 定期批量压缩(软删除)
- 转为
Set或加索引(如Map<Key, Value>)提升查找效率,再定位删除
但多数业务场景,迭代器删除或倒序索引删除已足够高效可靠。


















