Java集合迭代失效本质是迭代器对结构修改的响应策略差异,非并发专属问题;需依读写比例与一致性要求选容器:读远多于写用CopyOnWriteArrayList,读多写少用ConcurrentHashMap,高一致性场景应避免遍历中修改。

Java 中集合迭代失效问题,本质是迭代器对结构修改的响应策略不同,不是并发专属问题,单线程误操作也会触发 ConcurrentModificationException。关键在于:**先看清场景读写比例和一致性要求,再匹配容器机制,而不是一概用“线程安全版”替代。**
看清楚 Fail-Fast 和 Fail-Safe 的真实含义
Fail-Fast(如 ArrayList、HashMap 的迭代器)不是“不支持并发”,而是“拒绝模糊状态”——它通过维护一个 modCount 计数器,在每次调用 next() 前校验集合是否被非迭代器方式修改。一旦不一致,立刻报错,帮你提前发现逻辑错误或竞态风险。
Fail-Safe(如 CopyOnWriteArrayList、ConcurrentHashMap 的迭代器)不是“绝对安全”,而是“主动隔离变更”——它不依赖原集合实时状态,而是基于快照或弱一致性视图遍历,因此不会因其他线程写操作而中断,但你也看不到那些新写入的数据。
注意:Vector 和 Hashtable 虽然方法加了 synchronized,但它们的迭代器仍是 Fail-Fast 的,多线程遍历时仍可能抛异常;Collections.synchronizedList() 同理,只是给所有方法套了一把全局锁,迭代过程仍需手动同步,否则照样失败。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
按读写特征选容器:三类典型场景
-
读远多于写(读占比 >95%):选 CopyOnWriteArrayList / CopyOnWriteArraySet
适用监听器列表、配置白名单、静态规则集等场景。迭代完全无锁,性能极高;写操作(add/remove/set)会复制整个数组,所以写频繁时 GC 压力大、内存占用高。迭代器看到的是创建时的快照,期间新增/删除的元素本次遍历不可见。 -
读多写少(读占比 70%~90%,写有并发但不密集):选 ConcurrentHashMap
它不是 Fail-Safe 迭代器(JDK8+ 的迭代器是弱一致性),但允许遍历时其他线程修改,且不抛 CME。底层分段加锁 + CAS + 协同扩容,读操作几乎无锁,写操作只锁桶级。适合缓存、会话映射、统计计数等通用高并发键值场景。 -
写操作频繁或需强一致性(如金融扣款、事务上下文):避免依赖迭代器遍历改数据
这类场景本身就不该在遍历中做结构性修改。正确做法是:先收集待处理 key 或索引(如用 Stream.filter 或 removeIf),再批量操作;或改用显式锁(ReentrantLock)+ 普通集合,确保读写串行化;也可考虑阻塞队列(如 LinkedBlockingQueue)配合生产者-消费者模型解耦。
单线程下也别踩坑:安全遍历删除的正确姿势
即使没有多线程,增强 for 循环中调用 list.remove() 一样会抛 CME。这不是并发问题,是迭代器契约被破坏。
- 用
Iterator.remove():唯一被允许的边遍历边删方式,且只能删当前元素一次; - 用
list.removeIf(predicate):内部先遍历收集匹配项,再统一删除,语义清晰,推荐用于条件过滤; - 用 Stream API:如
list.stream().filter(...).collect(Collectors.toList()),适合生成新集合而非原地修改; - 倒序 for 循环:适用于已知索引删除,避免因删除导致后续元素前移而跳过;
- 绝不混用:不能在 Iterator 遍历中调用 list.add() 或 list.remove(i),哪怕单线程。
避坑提醒:几个常见误解
CopyOnWriteArrayList 不是万能 List 替代品——写开销大,不适合高频增删;
ConcurrentHashMap 的 keySet().iterator() 不保证反映最新写入,也不支持 remove() 操作(会抛 UnsupportedOperationException);
没有 CopyOnWriteHashMap —— JDK 只提供 CopyOnWriteArrayList 和 CopyOnWriteArraySet;
同步包装器(如 Collections.synchronizedList)只是“线程安全”的最低门槛,不是高性能解法,高并发下会成为瓶颈。

















