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 是集合遍历的“标准答案”,也是判断自己是否真正理解集合框架的重要依据。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐