iterator() 返回的是实现了 Iterator 接口的具体迭代器实例,如 ArrayList 返回其私有内部类 Itr,HashSet 返回 HashIterator 子类,它们在创建时记录集合的 modCount 值,并在 next() 或 hasNext() 中校验是否被并发修改。

Java 中 Collection 接口的 iterator() 方法返回一个迭代器,用于遍历集合元素;而 Fail-Fast(快速失败)机制是该迭代器在检测到集合被并发修改时主动抛出 ConcurrentModificationException 的保护策略。
iterator() 返回的是什么类型的对象?
调用 collection.iterator() 返回的是实现了 Iterator 接口的具体实例,例如 ArrayList 返回 Itr 内部类,HashSet 返回 HashIterator 子类。这些实现类在创建时会记录当前集合的 modCount(修改计数器)值,并在每次调用 next() 或 remove() 前校验该值是否与集合当前的 modCount 一致。
Fail-Fast 是如何触发的?
Fail-Fast 不是真正的并发控制机制,而是一种检测并报错的防御性设计。只要集合结构被修改(如 add/remove/clear),且修改不是由迭代器自身方法(如 iterator.remove())发起,下一次调用 next() 或 hasNext() 就会发现 expectedModCount != modCount,随即抛出异常。
- 注意:仅结构性修改触发检查(比如增删元素),修改元素内容(如
list.set(i, x))通常不改变modCount,不会触发 Fail-Fast - 单线程下也可能触发:比如边遍历边用集合自身的
remove()方法删除元素 - 多线程环境下,即使没有显式同步,只要多个线程同时修改集合,大概率触发异常(但不保证 100% 检测到)
如何安全地在遍历时修改集合?
若需在遍历过程中修改元素或删除匹配项,应使用迭代器提供的 remove() 方法,它会在删除后同步更新 expectedModCount,从而避免异常:
立即学习“Java免费学习笔记(深入)”;
- ✅ 正确:
Iterator<string> it = list.iterator(); while (it.hasNext()) { if (it.next().isEmpty()) it.remove(); }</string> - ❌ 错误:
for (String s : list) { if (s.isEmpty()) list.remove(s); }(触发 Fail-Fast) - 替代方案:收集待删元素后批量删除(
list.removeAll(toRemove)),或使用支持并发修改的集合(如CopyOnWriteArrayList、ConcurrentHashMap)
Fail-Fast 和 Fail-Safe 的区别
Fail-Fast 是大多数 java.util 包集合(ArrayList、HashMap、HashSet 等)迭代器的默认行为;而 Fail-Safe(如 ConcurrentHashMap 的 keySet 迭代器、CopyOnWriteArrayList 的迭代器)通过复制快照或分段锁等方式,允许遍历期间修改集合而不抛异常——但看到的可能是过期数据,且不反映实时修改。
选择取决于场景:需要强一致性且能控制修改方式 → 用 Fail-Fast + 迭代器 remove();需要高并发读写容忍弱一致性 → 选 Fail-Safe 集合。


















