【java】Iterator迭代器
本文系统讲解了Java中的Iterator迭代器,包括其设计思想、基本用法、核心特性和常见面试问题。Iterator是一种设计模式,用于在不暴露集合内部结构的前提下顺序访问元素,提供了统一的遍历接口。文章详细分析了Iterator解决的问题、使用方式、fail-fast机制、安全删除元素的方法,以及与ListIterator的区别。同时总结了面试常见问题和注意事项,强调Iterator是集合遍历的
Iterator 迭代器原理、用法与面试高频问题
在 Java 集合框架中,Iterator(迭代器) 是一个非常基础、却又经常被低估的接口。
它不仅是:
- for-each 循环的底层实现
- 集合遍历的统一方式
同时也是 面试中的高频考点,尤其是:
- fail-fast 机制
- 遍历过程中删除元素
- ConcurrentModificationException 的成因
本文将从 设计思想 → 基本用法 → 核心特性 → 面试问题 的顺序,系统讲解 Iterator。
一、什么是 Iterator?为什么需要它?
1️⃣ Iterator 的本质
Iterator 是一种设计模式,用于:
在不暴露集合内部结构的前提下,顺序访问集合中的元素。
它提供了一套统一的遍历接口,让我们不必关心集合的底层实现。
2️⃣ 没有 Iterator 之前的问题
在 Iterator 出现之前,遍历通常依赖集合本身的结构:
// 数组遍历
int[] arr = new int[10];
for (int i = 0; i < arr.length; i++) {
int value = arr[i];
}
// List 遍历
List<String> list = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
}
这种方式存在明显问题:
- ❌ 遍历逻辑和数据结构强耦合
- ❌ 不同集合写法不同,无法复用
- ❌ 集合类型变化,遍历代码也要改
3️⃣ Iterator 解决了什么?
Iterator 做的事情可以总结为一句话:
把“怎么遍历”这件事,从集合中抽离出来。
优点:
- 统一遍历方式
- 屏蔽底层结构
- 提高代码通用性和可维护性
二、Iterator 的基本使用方式
1️⃣ 获取 Iterator
Collection<String> collection = new ArrayList<>();
Iterator<String> iterator = collection.iterator();
所有实现了 Collection 接口的集合,都可以通过 iterator() 获取迭代器。
2️⃣ 遍历集合
while (iterator.hasNext()) {
String element = iterator.next();
// 处理元素
}
这是 Iterator 的标准用法模板。
3️⃣ 遍历过程中安全删除元素
while (iterator.hasNext()) {
String element = iterator.next();
if ("target".equals(element)) {
iterator.remove(); // 安全删除
}
}
⚠️ 这是 Iterator 非常重要的能力之一。
三、Iterator 的核心特性(面试重点)
1️⃣ fail-fast(快速失败机制)
核心现象:
在迭代过程中,如果集合被“非迭代器方式”修改,会抛出
ConcurrentModificationException
for (String s : list) {
list.remove(s); // ❌ 可能抛异常
}
底层原因(面试必考):
- 集合内部维护一个
modCount - Iterator 内部也维护一个期望的修改次数
- 两者不一致 → 立即抛异常
📌 目的不是线程安全,而是尽早暴露错误
2️⃣ 单向遍历
- Iterator 只能 从前往后
- 不支持反向遍历
👉 如果需要双向遍历,应使用 ListIterator
3️⃣ 统一遍历接口
无论底层集合是:
- ArrayList
- LinkedList
- HashSet
都可以使用同一套 Iterator 代码遍历。
📌 这正是 Iterator 设计的核心价值。
4️⃣ 惰性遍历(延迟加载)
Iterator:
- 每次只取一个元素
- 不会一次性加载全部数据
适合:
- 大数据量集合
- 流式处理场景
5️⃣ 支持安全删除(唯一正确方式)
✔ 正确:
iterator.remove();
❌ 错误:
collection.remove(element);
面试结论:
遍历时删除元素,只能用 Iterator 的 remove 方法。
四、Iterator 与 ListIterator 的区别(面试高频)
| 对比项 | Iterator | ListIterator |
|---|---|---|
| 适用集合 | List / Set | 仅 List |
| 遍历方向 | 单向 | 双向 |
| 是否可插入 | ❌ | ✅ |
| 是否可替换 | ❌ | ✅ |
| 继承关系 | 接口 | 继承 Iterator |
ListIterator 特有方法
hasPrevious()previous()add(E e)set(E e)
五、面试常考问题解析
1️⃣ 为什么遍历时修改集合会抛异常?
因为 Iterator 和集合内部维护的修改次数不一致,触发 fail-fast 机制。
2️⃣ 为什么不能用集合的 remove,而要用 iterator.remove?
- 集合的 remove 不会通知 Iterator
- Iterator.remove 会同步更新内部状态
3️⃣ for-each 和 Iterator 的关系?
- for-each 底层就是 Iterator
- 语法糖而已
- 删除元素仍然必须使用 Iterator
4️⃣ 为什么说 Iterator 是轻量级对象?
- 不复制集合
- 只保存当前位置指针
- 创建成本低
5️⃣ 为什么说 Iterator 提供了统一接口?
- 屏蔽集合差异
- 遍历逻辑与实现解耦
- 符合面向接口编程思想
六、常见错误与注意事项
1️⃣ next() 前必须 hasNext()
2️⃣ remove() 必须在 next() 之后
3️⃣ 不能连续调用 remove()
4️⃣ 只读集合可能不支持 remove()
七、综合示例
// List 遍历
List<String> list = new ArrayList<>(Arrays.asList("Java", "Python", "C++"));
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if ("Python".equals(s)) {
it.remove();
}
}
// Map 遍历
Map<Integer, String> map = new HashMap<>();
Iterator<Map.Entry<Integer, String>> mapIt = map.entrySet().iterator();
while (mapIt.hasNext()) {
Map.Entry<Integer, String> entry = mapIt.next();
System.out.println(entry.getKey() + " = " + entry.getValue());
}
八、总结
Iterator 是 Java 集合框架中极其重要但容易被忽视的接口。
你至少需要牢牢记住:
- Iterator 的设计目的
- fail-fast 机制的原理
- 遍历删除元素的正确方式
- Iterator 与 ListIterator 的区别
- for-each 的底层实现
一句话总结:
Iterator 是集合遍历的“标准答案”,也是判断自己是否真正理解集合框架的重要依据。
更多推荐



所有评论(0)