迭代器模式:集合遍历的统一之道
摘要
迭代器模式(Iterator Pattern)是行为型设计模式中的"集合导航专家",它提供了一种方法顺序访问聚合对象中的各个元素,而又不暴露其内部表示。本文将深入剖析迭代器模式的核心概念、实现方式、应用场景及高级变体,通过丰富的Java代码示例展示如何构建灵活的集合遍历机制,并分析其与访问者模式、组合模式的区别与适用场景。
一、迭代器模式核心思想
迭代器模式的核心是分离集合遍历与集合实现,具有以下关键特征:
- 统一接口:为不同集合提供一致的遍历方式
- 内部封装:隐藏集合的内部数据结构
- 多态迭代:支持多种遍历策略
- 并行遍历:支持多个同时进行的遍历
适用场景:
- 需要统一遍历不同结构的集合
- 需要支持多种遍历方式
- 需要隐藏集合的具体实现
- 需要为集合提供统一的接口
二、迭代器模式结构解析
UML类图示意
[Aggregate] <|-- [ConcreteAggregate]
[Iterator] <|-- [ConcreteIterator]
[ConcreteAggregate] --> [ConcreteIterator]
核心组件角色
角色 |
职责 |
典型实现 |
Iterator |
迭代器接口 |
定义遍历集合的方法 |
ConcreteIterator |
具体迭代器 |
实现特定集合的迭代逻辑 |
Aggregate |
聚合接口 |
定义创建迭代器的方法 |
ConcreteAggregate |
具体聚合 |
实现集合数据结构及迭代器创建 |
三、基础实现:自定义集合迭代器
// 迭代器接口
interface Iterator<T> {boolean hasNext();T next();void remove();
}// 聚合接口
interface IterableCollection<T> {Iterator<T> createIterator();
}// 具体聚合:自定义列表
class CustomList<T> implements IterableCollection<T> {private List<T> items = new ArrayList<>();public void add(T item) {items.add(item);}public T get(int index) {return items.get(index);}public int size() {return items.size();}@Overridepublic Iterator<T> createIterator() {return new ListIterator<>(this);}// 具体迭代器private class ListIterator<T> implements Iterator<T> {private CustomList<T> list;private int index = 0;public ListIterator(CustomList<T> list) {this.list = list;}@Overridepublic boolean hasNext() {return index < list.size();}@Overridepublic T next() {if (!hasNext()) {throw new NoSuchElementException();}return list.get(index++);}@Overridepublic void remove() {if (index <= 0) {throw new IllegalStateException();}list.items.remove(--index);}}
}// 客户端使用
public class IteratorDemo {public static void main(String[] args) {CustomList<String> list = new CustomList<>();list.add("Apple");list.add("Banana");list.add("Cherry");Iterator<String> iterator = list.createIterator();while (iterator.hasNext()) {System.out.println(iterator.next());}}
}
四、高级应用:树形结构迭代器
1. 二叉树迭代器
// 二叉树节点
class TreeNode<T> {T data;TreeNode<T> left;TreeNode<T> right;public TreeNode(T data) {this.data = data;}
}// 二叉树迭代器接口
interface TreeIterator<T> extends Iterator<T> {// 可添加树特有的遍历方法
}// 二叉树聚合
class BinaryTree<T> {private TreeNode<T> root;public void setRoot(TreeNode<T> root) {this.root = root;}public TreeIterator<T> createPreOrderIterator() {return new PreOrderIterator<>(root);}public TreeIterator<T> createInOrderIterator() {return new InOrderIterator<>(root);}public TreeIterator<T> createPostOrderIterator() {return new PostOrderIterator<>(root);}public TreeIterator<T> createLevelOrderIterator() {return new LevelOrderIterator<>(root);}
}// 前序遍历迭代器
class PreOrderIterator<T> implements TreeIterator<T> {private Stack<TreeNode<T>> stack = new Stack<>();public PreOrderIterator(TreeNode<T> root) {if (root != null) {stack.push(root);}}@Overridepublic boolean hasNext() {return !stack.isEmpty();}@Overridepublic T next() {if (!hasNext()) {throw new NoSuchElementException();}TreeNode<T> node = stack.pop();if (node.right != null) stack.push(node.right);if (node.left != null) stack.push(node.left);return node.data;}
}// 中序遍历迭代器
class InOrderIterator<T> implements TreeIterator<T> {private Stack<TreeNode<T>> stack = new Stack<>();private TreeNode<T> current;public InOrderIterator(TreeNode<T> root) {this.current = root;}@Overridepublic boolean hasNext() {return current != null || !stack.isEmpty();}@Overridepublic T next() {while (current != null) {stack.push(current);current = current.left;}TreeNode<T> node = stack.pop();current = node.right;return node.data;}
}// 使用示例
public class TreeIteratorDemo {public static void main(String[] args) {// 构建二叉树TreeNode<Integer> root = new TreeNode<>(1);root.left = new TreeNode<>(2);root.right = new TreeNode<>(3);root.left.left = new TreeNode<>(4);root.left.right = new TreeNode<>(5);BinaryTree<Integer> tree = new BinaryTree<>();tree.setRoot(root);// 前序遍历System.out.println("Pre-order traversal:");TreeIterator<Integer> preOrder = tree.createPreOrderIterator();while (preOrder.hasNext()) {System.out.print(preOrder.next() + " ");}// 中序遍历System.out.println("\nIn-order traversal:");TreeIterator<Integer> inOrder = tree.createInOrderIterator();while (inOrder.hasNext()) {System.out.print(inOrder.next() + " ");}}
}
2. 图遍历迭代器
// 图节点
class GraphNode<T> {T data;List<GraphNode<T>> neighbors = new ArrayList<>();public GraphNode(T data) {this.data = data;}public void addNeighbor(GraphNode<T> node) {neighbors.add(node);}
}// 图迭代器接口
interface GraphIterator<T> extends Iterator<T> {// 可添加图特有的遍历方法
}// 深度优先搜索迭代器
class DfsIterator<T> implements GraphIterator<T> {private Set<GraphNode<T>> visited = new HashSet<>();private Stack<GraphNode<T>> stack = new Stack<>();public DfsIterator(GraphNode<T> startNode) {if (startNode != null) {stack.push(startNode);visited.add(startNode);}}@Overridepublic boolean hasNext() {return !stack.isEmpty();}@Overridepublic T next() {if (!hasNext()) {throw new NoSuchElementException();}GraphNode<T> current = stack.pop();for (GraphNode<T> neighbor : current.neighbors) {if (!visited.contains(neighbor)) {stack.push(neighbor);visited.add(neighbor);}}return current.data;}
}// 广度优先搜索迭代器
class BfsIterator<T> implements GraphIterator<T> {private Set<GraphNode<T>> visited = new HashSet<>();private Queue<GraphNode<T>> queue = new LinkedList<>();public BfsIterator(GraphNode<T> startNode) {if (startNode != null) {queue.add(startNode);visited.add(startNode);}}@Overridepublic boolean hasNext() {return !queue.isEmpty();}@Overridepublic T next() {if (!hasNext()) {throw new NoSuchElementException();}GraphNode<T> current = queue.poll();for (GraphNode<T> neighbor : current.neighbors) {if (!visited.contains(neighbor)) {queue.add(neighbor);visited.add(neighbor);}}return current.data;}
}// 使用示例
public class GraphIteratorDemo {public static void main(String[] args) {// 构建图GraphNode<String> A = new GraphNode<>("A");GraphNode<String> B = new GraphNode<>("B");GraphNode<String> C = new GraphNode<>("C");GraphNode<String> D = new GraphNode<>("D");A.addNeighbor(B);A.addNeighbor(C);B.addNeighbor(D);C.addNeighbor(D);// DFS遍历System.out.println("DFS traversal:");GraphIterator<String> dfs = new DfsIterator<>(A);while (dfs.hasNext()) {System.out.print(dfs.next() + " ");}// BFS遍历System.out.println("\nBFS traversal:");GraphIterator<String> bfs = new BfsIterator<>(A);while (bfs.hasNext()) {System.out.print(bfs.next() + " ");}}
}
五、迭代器模式优缺点分析
优点:
优点 |
说明 |
单一职责 |
将遍历算法与集合分离 |
开闭原则 |
新增集合类型不影响现有代码 |
并行遍历 |
支持多个同时进行的遍历 |
统一接口 |
为不同集合提供一致遍历方式 |
封装性 |
隐藏集合内部实现细节 |
缺点:
缺点 |
说明 |
复杂度增加 |
简单集合使用迭代器可能过度设计 |
性能开销 |
间接访问可能带来轻微性能损失 |
修改限制 |
遍历过程中修改集合可能导致异常 |
六、迭代器模式与其他模式对比
迭代器模式 vs 访问者模式
维度 |
迭代器模式 |
访问者模式 |
目的 |
遍历集合元素 |
对元素执行操作 |
关注点 |
访问顺序 |
元素操作实现 |
元素耦合 |
元素类型无关 |
需要知道元素类型 |
扩展性 |
新增遍历方式容易 |
新增操作容易 |
迭代器模式 vs 组合模式
维度 |
迭代器模式 |
组合模式 |
目的 |
遍历集合元素 |
处理树形结构 |
关注点 |
元素访问顺序 |
部分-整体层次 |
结构 |
线性访问 |
递归结构 |
典型应用 |
集合遍历 |
UI组件、文件系统 |
七、迭代器模式最佳实践
1. 内部迭代器实现
// 内部迭代器接口
interface InternalIterator<T> {void forEach(Consumer<? super T> action);
}// 自定义集合实现内部迭代
class InternalList<T> implements InternalIterator<T> {private List<T> items = new ArrayList<>();public void add(T item) {items.add(item);}@Overridepublic void forEach(Consumer<? super T> action) {for (T item : items) {action.accept(item);}}
}// 使用示例
InternalList<String> names = new InternalList<>();
names.add("Alice");
names.add("Bob");
names.add("Charlie");names.forEach(System.out::println);
2. 过滤迭代器
// 过滤迭代器
class FilteringIterator<T> implements Iterator<T> {private Iterator<T> source;private Predicate<T> predicate;private T nextItem;private boolean hasNext;public FilteringIterator(Iterator<T> source, Predicate<T> predicate) {this.source = source;this.predicate = predicate;advance();}private void advance() {hasNext = false;while (source.hasNext()) {nextItem = source.next();if (predicate.test(nextItem)) {hasNext = true;break;}}}@Overridepublic boolean hasNext() {return hasNext;}@Overridepublic T next() {if (!hasNext) {throw new NoSuchElementException();}T result = nextItem;advance();return result;}
}// 使用示例
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
Iterator<Integer> evenNumbers = new FilteringIterator<>(numbers.iterator(), n -> n % 2 == 0
);while (evenNumbers.hasNext()) {System.out.println(evenNumbers.next());
}
3. 线程安全迭代器
// 线程安全集合
class ConcurrentCollection<T> {private final List<T> items = new ArrayList<>();private final ReadWriteLock lock = new ReentrantReadWriteLock();public void add(T item) {lock.writeLock().lock();try {items.add(item);} finally {lock.writeLock().unlock();}}public Iterator<T> iterator() {return new ConcurrentIterator();}// 线程安全迭代器private class ConcurrentIterator implements Iterator<T> {private final List<T> snapshot;private int index = 0;public ConcurrentIterator() {lock.readLock().lock();try {this.snapshot = new ArrayList<>(items);} finally {lock.readLock().unlock();}}@Overridepublic boolean hasNext() {return index < snapshot.size();}@Overridepublic T next() {if (!hasNext()) {throw new NoSuchElementException();}return snapshot.get(index++);}}
}// 使用示例
ConcurrentCollection<String> safeCollection = new ConcurrentCollection<>();
safeCollection.add("Item1");
safeCollection.add("Item2");// 多线程环境下安全遍历
new Thread(() -> {Iterator<String> it = safeCollection.iterator();while (it.hasNext()) {System.out.println("Thread1: " + it.next());}
}).start();new Thread(() -> {safeCollection.add("Item3");Iterator<String> it = safeCollection.iterator();while (it.hasNext()) {System.out.println("Thread2: " + it.next());}
}).start();
八、迭代器模式在开源框架中的应用
Java集合框架
// List接口扩展了Iterable
public interface List<E> extends Collection<E>, Iterable<E> {Iterator<E> iterator();// 其他方法...
}// ArrayList的迭代器实现
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable {public Iterator<E> iterator() {return new Itr();}private class Itr implements Iterator<E> {int cursor; // 下一个元素的索引int lastRet = -1; // 上一个返回的元素的索引public boolean hasNext() {return cursor != size;}public E next() {checkForComodification();int i = cursor;if (i >= size)throw new NoSuchElementException();Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length)throw new ConcurrentModificationException();cursor = i + 1;return (E) elementData[lastRet = i];}public void remove() {if (lastRet < 0)throw new IllegalStateException();checkForComodification();try {ArrayList.this.remove(lastRet);cursor = lastRet;lastRet = -1;expectedModCount = modCount;} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException();}}final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();}}
}
Spring Data的Repository
// Spring Data的查询方法返回Iterable
public interface UserRepository extends Repository<User, Long> {Iterable<User> findAllByActiveTrue();
}// 使用示例
@Autowired
private UserRepository userRepository;public void processActiveUsers() {Iterable<User> activeUsers = userRepository.findAllByActiveTrue();activeUsers.forEach(user -> {// 处理每个活跃用户});
}
九、高级应用:惰性求值迭代器
1. 数据库结果集迭代器
// 数据库结果集迭代器
class DatabaseResultIterator<T> implements Iterator<T> {private ResultSet resultSet;private RowMapper<T> rowMapper;private boolean hasNext;public DatabaseResultIterator(ResultSet resultSet, RowMapper<T> rowMapper) {this.resultSet = resultSet;this.rowMapper = rowMapper;this.hasNext = moveToNext();}private boolean moveToNext() {try {return resultSet.next();} catch (SQLException e) {throw new RuntimeException("Database access error", e);}}@Overridepublic boolean hasNext() {return hasNext;}@Overridepublic T next() {if (!hasNext) {throw new NoSuchElementException();}try {T item = rowMapper.mapRow(resultSet, resultSet.getRow());hasNext = moveToNext();return item;} catch (SQLException e) {throw new RuntimeException("Mapping failed", e);}}
}// 行映射器接口
interface RowMapper<T> {T mapRow(ResultSet rs, int rowNum) throws SQLException;
}// 使用示例
public List<User> findAllUsers(Connection conn) throws SQLException {Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery("SELECT * FROM users");Iterator<User> iterator = new DatabaseResultIterator<>(rs, rs -> {User user = new User();user.setId(rs.getLong("id"));user.setName(rs.getString("name"));return user;});List<User> users = new ArrayList<>();iterator.forEachRemaining(users::add);return users;
}
2. 无限序列迭代器
// 斐波那契数列迭代器
class FibonacciIterator implements Iterator<BigInteger> {private BigInteger current = BigInteger.ZERO;private BigInteger next = BigInteger.ONE;@Overridepublic boolean hasNext() {return true; // 无限序列}@Overridepublic BigInteger next() {BigInteger result = current;current = next;next = result.add(current);return result;}
}// 使用示例(需要限制数量)
public class InfiniteSequenceDemo {public static void main(String[] args) {Iterator<BigInteger> fib = new FibonacciIterator();Stream.generate(() -> fib.next()).limit(20).forEach(System.out::println);}
}
十、迭代器模式未来发展趋势
新兴应用方向:
- 大数据处理:分布式集合的迭代器
- 响应式编程:异步数据流迭代
- 函数式编程:惰性求值迭代器
- AI数据处理:大规模训练数据集遍历
- 区块链:链上数据顺序访问
响应式迭代器
// Reactor中的Flux迭代器
Flux<Integer> flux = Flux.range(1, 10).map(i -> i * 2).filter(i -> i % 3 == 0);// 订阅处理相当于迭代
flux.subscribe(System.out::println, // onNextThrowable::printStackTrace, // onError() -> System.out.println("Completed") // onComplete
);// 或者转换为Iterable
Iterable<Integer> iterable = flux.toIterable();
for (Integer num : iterable) {System.out.println(num);
}
总结
迭代器模式是处理集合遍历的通用解决方案,它通过以下方式提升系统质量:
- 统一遍历接口:为不同集合提供一致的访问方式
- 解耦集合与算法:分离遍历逻辑与数据结构
- 并行遍历支持:允许多个同时进行的遍历
- 封装实现细节:隐藏集合的内部表示
现代应用关键点:
- 函数式集成:结合Stream API和Lambda表达式
- 惰性求值:实现高效的大数据集处理
- 线程安全:设计并发环境下的安全迭代器
- 资源管理:正确处理IO资源的关闭
- 性能优化:避免不必要的对象创建
迭代器模式正在与函数式编程、响应式编程等现代范式结合,演进出更强大的数据处理能力。理解并掌握迭代器模式的精髓,将帮助开发者构建出更加灵活、高效的集合处理系统,特别是在大数据和分布式计算领域。