← 返回题目列表

什么是迭代器模式?它解决什么问题?

高频 简单 第 2 / 25 题 更新于 2026/07/28
迭代器模式行为型模式集合遍历

简化版

迭代器模式是一种把集合遍历逻辑从集合对象中分离出来的行为型设计模式。它让客户端不需要知道集合的内部结构,就能按统一方式逐个访问元素。

详细版

迭代器模式解决的是“如何遍历集合,同时不暴露集合内部表示”的问题。

比如数组、链表、树、图的存储结构不同,如果客户端直接依赖它们的内部结构,遍历代码就会和集合实现强耦合。迭代器模式提供一个统一的访问对象,客户端只关心:

  • 是否还有下一个元素。
  • 获取下一个元素。
  • 必要时删除当前元素。

集合负责创建迭代器,迭代器负责维护遍历位置。这样集合可以改变内部结构,而客户端遍历代码基本不变。

完整版教学

一、为什么需要迭代器模式

集合对象通常有自己的内部结构。例如:

  • 数组用连续下标访问。
  • 链表要沿着节点指针走。
  • 树可能有前序、中序、后序、层序遍历。
  • 图可能有 BFS 或 DFS。

如果客户端直接写这些遍历逻辑,就会出现两个问题。

第一,客户端必须了解集合内部结构。链表怎么走指针、树怎么递归、图怎么去重,都会泄露到外部代码中。

第二,遍历逻辑容易重复。多个地方都要遍历同一个集合时,就可能到处复制类似代码。

迭代器模式把遍历过程封装成一个独立对象,让客户端面向统一接口访问元素。

二、迭代器模式的核心思想

迭代器模式的核心是:集合保存数据,迭代器负责遍历。

集合对象不再把内部存储细节暴露给客户端,而是提供一个创建迭代器的方法。客户端拿到迭代器后,只按迭代器接口访问。

典型接口类似:

interface Iterator<E> {
    boolean hasNext();
    E next();
}

客户端不需要知道底层是数组还是链表,只要按 hasNext()next() 使用即可。

三、它保护了集合的封装性

如果集合直接暴露内部数组:

Object[] elements = list.getElements();

客户端就可能依赖数组下标、容量、扩容策略,甚至修改内部数据。集合的封装性被破坏。

迭代器只暴露遍历行为,不暴露内部结构。集合以后从数组换成链表,客户端遍历代码也不一定需要修改。

四、它支持多种遍历方式

同一个集合可能有多种遍历顺序。

例如一棵二叉树可以提供:

  • 前序迭代器。
  • 中序迭代器。
  • 后序迭代器。
  • 层序迭代器。

这些遍历算法可以各自封装在不同迭代器里,而不是把所有遍历逻辑堆进树对象。

五、迭代器模式不是只为 Java 集合服务

Java 集合中的 Iterator 是迭代器模式的经典应用,但这个模式并不限于集合框架。

实际项目中,只要存在“按顺序访问一组对象,但不想暴露内部结构”的场景,都可以使用迭代器思想。例如分页结果遍历、游标查询、文件行读取、组合树遍历等。

六、常见误区与追问

迭代器模式把遍历状态和顺序从集合及客户端中抽离。对含5个元素的集合,Iterator 用游标依次暴露元素,而客户端不必知道底层是数组下标还是链表节点。每次遍历创建独立 Iterator,集合可以保持数据职责,客户端获得统一协议。

检查维度判定依据
集合职责保存元素并创建迭代器
迭代器职责保存游标并按顺序返回元素
hasNext? -> next -> hasNext? -> ... -> end

记忆钩子:迭代器把“怎么走”封装起来,只把“下一个是谁”交给客户端。

  • 误区:迭代器就是普通 for 循环。 它是封装游标和访问协议的对象,可跨多种存储结构复用客户端代码。
  • 追问:为什么属于行为型模式? 它定义集合与客户端之间如何协作完成遍历。
  • 误区:迭代器必须一次加载全部元素。 它可以惰性读取流、分页数据或生成序列。
  • 追问:集合修改时会怎样? 取决于具体契约,可能 fail-fast、快照或弱一致。
  • 追问:增强 for 与它有什么关系? Java 对 Iterable 使用增强 for 时,底层通过 Iterator 推进。

七、加强记忆

迭代器模式可以记成“集合管存储,迭代器管走法”:客户端只通过统一接口一步步取元素,不关心集合内部结构,也不把遍历逻辑散落在业务代码里。