| name | Iterator |
| description | 提供一种方法顺序访问容器中的各个元素 |
| license | MIT |
Iterator Pattern (迭代器模式)
核心概念
Iterator是一种Behavioral设计模式。
定义: 提供一种方法来顺序访问一个聚合对象中的各个元素,而不暴露该对象的内部表示。它将集合的遍历与其内部结构分离。
核心思想
- 遍历算法与集合分离: 集合不需要知道遍历算法
- 统一接口: 所有迭代器遵循同一接口
- 多种遍历方式: 支持前向、反向、深度优先等多种遍历
- 延迟计算: 支持惰性求值和无限序列
何时使用
触发条件
- 集合结构多样 - 数组、链表、树等,需要统一遍历
- 多种遍历方式 - 同一个集合需要正向、反向、按文件夹等遍历
- 隐藏内部结构 - 集合实现细节不想暴露
- 支持并发遍历 - 同时进行多个遍历
- 需要延迟加载 - 如数据库查询集合、无限序列
不适合场景
- ❌ 简单的数组或List - 直接使用for循环即可
- ❌ 一维序列 - 顺序遍历就足够了
- ❌ 性能极端敏感 - 迭代器有额外开销
基本结构
参与者
- Iterator - 迭代器接口,定义遍历元素的方法
- ConcreteIterator - 具体迭代器,实现遍历逻辑
- Aggregate - 聚合对象接口,提供创建迭代器的方法
- ConcreteAggregate - 具体集合
UML关系
┌──────────────────┐
│ Iterator │
├──────────────────┤
│ + next() │
│ + hasNext() │
│ + remove() │
└──────────────────┘
△
│ implements
┌────┴─────────────────┐
│ │
┌──────────────────┐ ┌────────────────────┐
│ListIterator │ │TreeIterator │
├──────────────────┤ ├────────────────────┤
│ - current │ │ - stack │
│ + next() │ │ + next() │
└──────────────────┘ └────────────────────┘
▲ ▲
│ │
┌────┴──────────────────────┴───────┐
│ │
┌──────────────────┐ ┌──────────────────┐
│ Aggregate │ │ ConcreteAggregate│
├──────────────────┤ ├──────────────────┤
│+ createIterator()│─────────→│ - elements: List │
└──────────────────┘ │+ createIterator()│
└──────────────────┘
实现方式对比
方法1: 外部迭代器 (Classic)
特点: 集合外部管理遍历状态
interface Iterator<T> {
boolean hasNext();
T next();
void remove();
}
class ListIterator<T> implements Iterator<T> {
private List<T> list;
private int currentIndex = 0;
ListIterator(List<T> list) {
this.list = list;
}
@Override
public boolean hasNext() {
return currentIndex < list.size();
}
@Override
public T next() {
if (!hasNext()) throw new NoSuchElementException();
return list.get(currentIndex++);
}
@Override
public void remove() {
list.remove(--currentIndex);
}
}
List<String> names = Arrays.asList("Alice", "Bob", "Carol");
Iterator<String> iterator = new ListIterator<>(names);
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
方法2: 内部迭代器
特点: 集合内部管理遍历,通过回调处理元素
interface Collection<T> {
void forEach(Consumer<T> action);
}
class MyCollection<T> implements Collection<T> {
private T[] elements;
@Override
public void forEach(Consumer<T> action) {
for (T element : elements) {
action.accept(element);
}
}
}
MyCollection<String> collection = new MyCollection<>();
collection.forEach(System.out::println);
方法3: 生成器风格的迭代器
特点: 使用生成器或协程处理无限序列
abstract class Generator<T> {
abstract void execute();
protected void yield(T value) {
}
}
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
gen = fibonacci()
for i in range(10):
print(next(gen))
方法4: 异步迭代器
特点: 支持异步操作,如异步I/O
async function* asyncGenerator() {
for (let i = 0; i < 5; i++) {
await delay(1000);
yield i;
}
}
for await (const value of asyncGenerator()) {
console.log(value);
}
6个真实使用场景
场景1: 数据库游标 (Database Cursor)
应用: JDBC ResultSet, ORM框架
try (Statement stmt = connection.createStatement()) {
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
while (rs.next()) {
System.out.println(rs.getString("name"));
}
}
class DatabaseIterator implements Iterator<Record> {
private ResultSet resultSet;
@Override
public boolean hasNext() {
try {
return resultSet.next();
} catch (SQLException e) {
return false;
}
}
@Override
public Record next() {
try {
return mapRecord(resultSet);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
场景2: DOM树遍历 (DOM Traversal)
应用: XML/HTML解析, DOM操作
interface NodeIterator {
Node nextNode();
}
class DepthFirstIterator implements NodeIterator {
private Stack<Node> stack;
public DepthFirstIterator(Node root) {
stack = new Stack<>();
stack.push(root);
}
@Override
public Node nextNode() {
if (stack.isEmpty()) return null;
Node node = stack.pop();
for (int i = node.getChildCount() - 1; i >= 0; i--) {
stack.push(node.getChild(i));
}
return node;
}
}
场景3: 集合框架 (Collection Framework)
应用: Java Collections Framework
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
Iterator<String> iter1 = list.iterator();
while (iter1.hasNext()) {
System.out.println(iter1.next());
}
list.forEach(System.out::println);
for (String item : list) {
System.out.println(item);
}
场景4: 目录文件遍历 (File System)
应用: 文件系统遍历, 递归查找
class DirectoryIterator {
private Queue<File> queue = new LinkedList<>();
public DirectoryIterator(File root) {
queue.offer(root);
}
public File next() {
if (queue.isEmpty()) return null;
File file = queue.poll();
if (file.isDirectory()) {
for (File child : file.listFiles()) {
queue.offer(child);
}
}
return file;
}
}
try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
for (Path file : stream) {
System.out.println(file);
}
}
场景5: 分页和游标 (Pagination)
应用: Web框架分页, API游标
class PageIterator<T> implements Iterator<T> {
private int pageSize;
private int currentPage = 0;
private List<T> currentPageData;
private DataRepository repo;
@Override
public boolean hasNext() {
if (currentPageData == null) {
loadNextPage();
}
return !currentPageData.isEmpty();
}
@Override
public T next() {
if (currentPageData == null || currentPageData.isEmpty()) {
loadNextPage();
}
return currentPageData.remove(0);
}
private void loadNextPage() {
currentPageData = repo.findPage(currentPage++, pageSize);
}
}
场景6: 流和管道处理 (Stream/Pipeline)
应用: 函数式编程, 数据流处理
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream()
.filter(n -> n > 2)
.map(n -> n * 2)
.forEach(System.out::println);
class StreamIterator<T> implements Iterator<T> {
private List<T> data;
private Function<T, Boolean> filter;
private Function<T, T> transform;
private int index = 0;
@Override
public boolean hasNext() {
while (index < data.size()) {
if (filter.apply(data.get(index))) {
return true;
}
index++;
}
return false;
}
@Override
public T next() {
return transform.apply(data.get(index++));
}
}
4个常见问题及解决方案
问题1: 并发修改异常 (Concurrent Modification)
症状:
- 遍历集合时添加/删除元素导致异常
- fail-fast行为
解决方案:
List<String> list = new ArrayList<>();
list.add("A"); list.add("B"); list.add("C");
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
String item = iter.next();
if (item.equals("B")) {
iter.remove();
}
}
for (String item : list) {
if (item.equals("B")) {
list.remove(item);
}
}
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
List<String> cowList = new CopyOnWriteArrayList<>(list);
for (String item : cowList) {
if (item.equals("B")) {
cowList.remove(item);
}
}
问题2: 延迟加载和无限序列
症状:
解决方案:
abstract class LazyIterator<T> implements Iterator<T> {
protected abstract T loadNext();
@Override
public T next() {
return loadNext();
}
}
class FibonacciIterator implements Iterator<Long> {
private long prev = 0, curr = 1;
@Override
public boolean hasNext() {
return true;
}
@Override
public Long next() {
long next = prev + curr;
prev = curr;
curr = next;
return prev;
}
}
FibonacciIterator fib = new FibonacciIterator();
for (int i = 0; i < ; i++) {
System.out.println(fib.next());
}
问题3: 复杂的遍历模式
症状:
- 需要多种遍历方式(BFS, DFS, Level-order等)
- 遍历逻辑复杂且易出错
解决方案:
interface TreeIterator<T> extends Iterator<T> {}
class PreOrderIterator<T> implements TreeIterator<T> {
private Stack<TreeNode<T>> stack;
public PreOrderIterator(TreeNode<T> root) {
stack = new Stack<>();
stack.push(root);
}
@Override
public boolean hasNext() {
return !stack.isEmpty();
}
@Override
public T next() {
TreeNode<T> node = stack.pop();
if (node.right != null) stack.push(node.right);
if (node.left != null) stack.push(node.left);
return node.value;
}
}
class InOrderIterator<T> implements TreeIterator<T> {
private Stack<TreeNode<T>> stack = new Stack<>();
private TreeNode<T> current;
public InOrderIterator(TreeNode<T> root) {
current = root;
}
@Override
public boolean hasNext {
current != || !stack.isEmpty();
}
T {
(current != ) {
stack.push(current);
current = current.left;
}
current = stack.pop();
current.value;
current = current.right;
result;
}
}
问题4: 快照 vs 动态视图
症状:
- 迭代器返回的是集合当前状态的快照还是动态视图?
- 集合修改是否影响已创建的迭代器?
解决方案:
class SnapshotIterator<T> implements Iterator<T> {
private List<T> snapshot;
private int index = 0;
public SnapshotIterator(List<T> original) {
this.snapshot = new ArrayList<>(original);
}
@Override
public boolean hasNext() {
return index < snapshot.size();
}
@Override
public T next() {
return snapshot.get(index++);
}
}
class DynamicViewIterator<T> implements Iterator<T> {
private List<T> original;
private int index = 0;
public DynamicViewIterator(List<T> original) {
this.original = original;
}
@Override
public boolean hasNext() {
return index < original.size();
}
T {
(index >= original.size()) {
();
}
original.get(index++);
}
}
List<String> list = <>();
Iterator<String> snapshot = <>(list);
Iterator<String> dynamic = <>(list);
与其他模式的关系
| 模式 | 关系 | 何时结合 |
|---|
| Composite | 遍历树形结构 | 树的递归遍历 |
| Factory | 创建正确的迭代器 | 根据集合类型选择迭代器 |
| Strategy | 不同的遍历算法 | 支持多种遍历方式 |
| Visitor | 访问集合中的元素 | 结合迭代器遍历和元素操作 |
| Observer | 订阅集合变化 | 遍历时响应集合变化 |
最佳实践
1. 遵循Iterator接口
public class MyIterator implements Iterator<T> {
@Override
public boolean hasNext() { }
@Override
public T next() { }
@Override
public void remove() { }
}
2. 提供多种遍历方式
class TreeNode<T> {
Iterator<T> preOrder() { }
Iterator<T> inOrder() { }
Iterator<T> postOrder() { }
Iterator<T> levelOrder() { }
}
3. 考虑fail-fast行为
class SafeIterator<T> implements Iterator<T> {
private int modCount;
private int expectedModCount;
@Override
public T next() {
checkConcurrentModification();
return ...;
}
private void checkConcurrentModification() {
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
}
何时避免使用
- ❌ 简单的for循环足够 - 不需要为此创建迭代器
- ❌ 单一遍历方式 - 直接遍历即可
- ❌ 性能关键 - 迭代器有额外开销
总结
迭代器模式通过提供统一的遍历接口,将集合的结构与遍历算法分离,提供了灵活的遍历机制。现代语言(如Java的Stream API、Python的生成器)已经内置了迭代器的强大功能,使该模式更容易使用。