Iterator 是临时生成的一次性访问代理,用于安全遍历集合;它剥离了遍历逻辑与集合实现,支持统一的 hasNext()/next() 接口,并允许通过 remove() 安全修改集合。

Iterator 是用来安全遍历集合的“只读游标”
它不是容器,也不是数据本身,而是一个**临时生成的、一次性的访问代理**。你调用 list.iterator() 得到的不是集合副本,而是指向当前集合状态的一个轻量级指针——它知道“下一个该取谁”,但不负责存储或管理数据。
关键在于:它把“怎么取元素”从集合实现里剥离开。无论你面对的是 ArrayList(数组)、LinkedList(链表)还是 HashSet(哈希表),都用同一套 hasNext()/next() 逻辑,不用记下标、不操心索引越界、也不用管底层是顺序还是散列。
为什么不能直接 for 循环删元素,却能用 Iterator.remove()?
因为普通 for 或增强 for 遍历时,集合内部的修改计数器(modCount)和迭代器预期的版本不一致,会立刻抛 ConcurrentModificationException;而 iterator.remove() 是唯一被允许的“边走边改”操作——它同步更新了计数器,让迭代器和集合保持步调一致。
- ✅ 正确:先
next(),再remove()(且只能调一次) - ❌ 错误:
remove()前没调next()→IllegalStateException - ❌ 错误:连续两次
remove()→ 同样抛IllegalStateException - ❌ 错误:用
list.remove(obj)替代iterator.remove()→ 必爆并发修改异常
ListIterator 和普通 Iterator 有什么实际区别?
ListIterator 是 Iterator 的子接口,只适用于 List 类型,核心价值在「双向 + 可写」:
立即学习“Java免费学习笔记(深入)”;
- 支持
previous()和hasPrevious(),能倒着走 - 支持
add():在当前位置插入新元素(不影响当前指针) - 支持
set():替换上一次next()或previous()返回的元素 - 不支持
Map或Set,强行转型会报ClassCastException
比如你需要边遍历边在每两个元素之间插一个分隔符,或者从后往前找并删掉最后一个匹配项——这时候 ListIterator 就不可替代。
迭代器失效、空指针、NoSuchElementException 怎么避坑?
迭代器本身不保存状态,一旦集合被外部修改(比如另一个线程改了,或本线程用非迭代器方式删了),它就立即失效;而 next() 调用前不检查 hasNext(),就会崩出 NoSuchElementException。
- 每次
next()前必须配对hasNext(),别偷懒写成while(true) { it.next(); } - 迭代器不能复用:用完就丢,要重遍历就得再调一次
collection.iterator() - 多线程场景下,即使用了
Iterator,也不能解决并发修改问题——得上CopyOnWriteArrayList或加锁 -
map.keySet().iterator()和map.values().iterator()返回的迭代器互不影响,但都依赖原HashMap的结构稳定性
最常被忽略的一点:remove() 是可选操作。某些集合(如 Arrays.asList() 包装的列表)返回的迭代器不支持删除,调用就抛 UnsupportedOperationException——得先看文档,或用 try-catch 容错。










