java中安全删除集合元素应避免concurrentmodificationexception:单线程用iterator.remove()或removeif();多线程选copyonwritearraylist或concurrenthashmap;复杂逻辑可暂存待删元素再统一移除。

Java 中 Iterator 本身不处理并发修改异常,它只是检测并抛出 ConcurrentModificationException。真正“处理”该异常的方式,是避免触发它——不是靠 try-catch 捕获,而是从设计和用法上消除非法修改的可能。
单线程遍历中安全删除元素
在 for-each 或 while + hasNext() 遍历时,若需删除匹配项,唯一安全的做法是调用 Iterator 自身的 remove() 方法:
- 它会同步更新内部的
expectedModCount,使下次hasNext()或next()不再校验失败 - 必须在调用
next()之后、下一次next()之前调用;重复调用或提前调用会抛IllegalStateException - 增强 for 循环中无法使用,因拿不到 Iterator 实例
更简洁的替代写法:removeIf()
Java 8 起推荐用 集合自身的 removeIf() 方法:
- 语义明确:“移除所有满足条件的元素”
- 底层仍基于安全迭代逻辑,无需手动管理 Iterator
- 适用于 List、Set 等支持该方法的集合,例如:
list.removeIf(s -> s == null || s.isEmpty())
多线程环境必须换容器,不能靠加锁 Iterator
Iterator 的 fail-fast 机制不是线程安全方案。多线程读写时,应选用专为并发设计的集合:
- CopyOnWriteArrayList:遍历时用快照,写操作复制新数组;适合读远多于写的场景(如监听器列表)
- ConcurrentHashMap:其 keySet() / values() 返回的 Iterator 是弱一致性的,不抛 CME,且能保证遍历的是某一时刻的稳定视图
- 避免用
Collections.synchronizedList():仅方法级加锁,遍历过程仍需额外同步块,易遗漏且性能差
复杂逻辑兜底:暂存后统一删除
当判断条件太复杂、无法用 removeIf,又不想引入新集合类型时,可采用两阶段策略:
- 第一阶段:遍历原集合,只做判断,把待删元素存入临时集合(如
new ArrayList()) - 第二阶段:遍历结束后,调用
list.removeAll(toRemove)或逐个remove() - 若原集合是 HashSet,用 HashSet 存待删项可提升
removeAll效率
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











