Java集合迭代“失效”实为fail-fast机制主动中断,通过modCount与expectedModCount比对检测结构性修改(如add、remove、clear),不一致则抛ConcurrentModificationException,强制遵循迭代器语义。

Java 中 Iterator 迭代器失效,本质是 fail-fast(快速失败)机制被触发,不是迭代器“自己坏了”,而是它检测到集合在迭代过程中被**结构性修改**(即增、删元素),于是主动抛出 ConcurrentModificationException。
什么算“结构性修改”?
对集合本身执行以下操作会改变其内部结构:
- 调用
list.add()、list.remove()、set.add()等直接修改集合的方法 - 调用
list.clear()、list.addAll()等批量变更方法 - 使用增强 for 循环(底层就是 Iterator)时,在循环体内直接修改原集合
注意:仅修改元素内容(如 list.get(i).setName("xxx"))不算结构性修改,不会触发失效。
Iterator 自己的 remove() 是安全的
Iterator 提供的 remove() 方法是唯一被允许的、在遍历时安全删除当前元素的方式:
立即学习“Java免费学习笔记(深入)”;
- 它会同步更新迭代器内部的
expectedModCount,与集合的modCount保持一致 - 必须在
next()之后调用,且每个next()最多调用一次remove()
例如:
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if ("b".equals(s)) it.remove(); // ✅ 安全
}
为什么 HashMap 的 keySet()/entrySet() 迭代也会失效?
因为这些视图(View)返回的 Iterator 同样依赖底层 HashMap 的 modCount。只要对 map 执行了 put()、remove()、clear() 等结构性操作,再继续用之前的迭代器遍历,就会立即抛异常。
即使你只迭代 keySet(),同时在别处 map.put("newKey", "v"),也会触发失效。
如何避免失效?
- 遍历时需要删元素 → 用 Iterator.remove()
-
需要批量删/改 → 先收集待操作元素,遍历结束后再统一处理(如用
removeIf()、或先存入临时 List 再调removeAll()) -
多线程场景 → 用并发集合(如
CopyOnWriteArrayList、ConcurrentHashMap),它们不基于 fail-fast,而是采用其他线程安全策略


















