Java集合迭代时应避免ConcurrentModificationException:单线程用Iterator.remove()或removeIf();多线程用CopyOnWriteArrayList或ConcurrentHashMap;复杂逻辑可暂存待删元素再统一移除。

Java 集合迭代时用 Iterator 避免 ConcurrentModificationException,核心不是“捕获异常”,而是从用法上杜绝触发条件。Iterator 本身不处理异常,它只检测并抛出——真正安全的方式,是让修改动作与迭代器状态同步。
必须用 Iterator.remove() 删除元素
这是单线程下最标准、最可靠的做法:
- 调用
it.next()获取元素后,立即用it.remove()删除,它会自动更新内部的expectedModCount,使下次hasNext()校验通过 - 不能在
next()前调用remove(),也不能对同一元素连续调用两次remove(),否则抛IllegalStateException - 增强 for 循环(
for (String s : list))拿不到 Iterator 实例,无法使用该方式,直接调用list.remove()必然触发异常
优先考虑 removeIf() 替代手写循环
Java 8 起,集合自带的 removeIf() 是更简洁、更安全的选择:
- 语义清晰:“移除所有满足条件的元素”,一行代码解决
- 底层仍基于安全的 Iterator 逻辑,无需手动管理游标和调用时机
- 支持
ArrayList、LinkedList、HashSet等主流集合,例如:list.removeIf(s -> s == null || s.trim().isEmpty())
多线程环境不能靠加锁 Iterator
Iterator 的 fail-fast 机制不是线程安全方案。同步块包裹遍历过程容易遗漏、性能差,且不能保证逻辑正确:
- 推荐换用专为并发设计的集合:
CopyOnWriteArrayList(读多写少,如事件监听器列表)或ConcurrentHashMap(其keySet().iterator()是弱一致性的,不抛 CME) - 避免使用
Collections.synchronizedList()配合普通 Iterator,因为迭代过程本身未受保护,仍可能出错 -
CopyOnWriteArrayList的迭代器不支持remove(),调用会抛UnsupportedOperationException
复杂判断逻辑可暂存后统一删除
当删除条件涉及多个字段、外部状态或耗时计算,不适合写进 removeIf() 的 lambda 时:
- 第一阶段:遍历原集合,仅做判断,把待删元素加入临时集合(如
new ArrayList()) - 第二阶段:遍历结束后,调用
list.removeAll(toRemove);若原集合是HashSet,用HashSet存待删项可提升效率 - 该方式不依赖迭代器状态,也不要求集合类型支持特定方法,适用性广
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











