
1. 迭代器模式的核心概念解析迭代器模式Iterator Pattern可能是我们日常编码中接触最多却最容易被忽视的设计模式。每当你使用Java的for-each循环遍历集合或者在Python中调用next()获取序列的下一个元素时其实都在不自觉地使用迭代器模式。这种模式的核心价值在于它提供了一种统一的方式来访问聚合对象中的各个元素而又不暴露该对象的内部表示。想象一下你去图书馆借书的场景。作为读者你不需要知道图书馆是如何存储和管理书籍的是按分类号排列在书架上还是存放在地下书库你只需要通过图书检索系统找到想要的书籍然后按照索书号去相应区域取书即可。迭代器模式就是这个图书检索系统它把复杂的存储逻辑隐藏在背后为你提供简单的下一本书的访问接口。从技术实现角度看迭代器模式包含以下几个关键角色Iterator迭代器接口定义访问和遍历元素的接口通常包含hasNext()、next()等方法ConcreteIterator具体迭代器实现迭代器接口负责管理当前遍历的位置Aggregate聚合接口定义创建迭代器对象的接口ConcreteAggregate具体聚合实现聚合接口返回一个合适的具体迭代器实例提示现代编程语言大多已经内置了迭代器支持比如Java的Iterable接口和Iterator接口C#的IEnumerable和IEnumeratorPython的__iter__()和__next__()方法等。理解语言原生支持的迭代器实现方式能帮助我们更好地使用它们。2. 迭代器模式的典型实现与语言差异2.1 Java中的迭代器实现Java对迭代器模式的支持堪称教科书级别的实现。我们来看一个完整的示例// 迭代器接口 public interface IteratorT { boolean hasNext(); T next(); default void remove() { throw new UnsupportedOperationException(remove); } } // 可迭代集合接口 public interface IterableT { IteratorT iterator(); } // 具体集合实现 public class BookShelf implements IterableBook { private Book[] books; private int last 0; public BookShelf(int size) { this.books new Book[size]; } public Book getBookAt(int index) { return books[index]; } public void appendBook(Book book) { this.books[last] book; last; } public int getLength() { return last; } Override public IteratorBook iterator() { return new BookShelfIterator(this); } } // 具体迭代器实现 public class BookShelfIterator implements IteratorBook { private BookShelf bookShelf; private int index; public BookShelfIterator(BookShelf bookShelf) { this.bookShelf bookShelf; this.index 0; } Override public boolean hasNext() { return index bookShelf.getLength(); } Override public Book next() { Book book bookShelf.getBookAt(index); index; return book; } }这个实现展示了几个关键点分离了集合结构和遍历逻辑BookShelf只负责存储书籍BookShelfIterator负责遍历支持多种遍历方式可以创建不同的迭代器实现如前序遍历、后序遍历等符合开闭原则新增迭代方式不需要修改集合类2.2 Python的迭代器协议Python通过迭代器协议Iterator Protocol实现了更灵活的迭代机制。任何实现了__iter__()和__next__()方法的对象都可以作为迭代器使用class CountDown: def __init__(self, start): self.current start self.start start def __iter__(self): return self def __next__(self): if self.current 0: raise StopIteration else: self.current - 1 return self.current 1 # 使用示例 for num in CountDown(5): print(num) # 输出 5 4 3 2 1Python的生成器Generator是迭代器的语法糖实现使用yield关键字可以更简洁地创建迭代器def count_down(start): while start 0: yield start start - 1 # 使用方式与类实现的迭代器完全相同 for num in count_down(5): print(num)2.3 C中的迭代器实现C通过STL提供了强大的迭代器支持标准库容器都提供了相应的迭代器类型。现代CC11之后还引入了基于范围的for循环进一步简化了迭代操作#include iostream #include vector int main() { std::vectorint vec {1, 2, 3, 4, 5}; // 传统迭代器用法 for (auto it vec.begin(); it ! vec.end(); it) { std::cout *it ; } // 基于范围的for循环底层仍然使用迭代器 for (int num : vec) { std::cout num ; } return 0; }3. 迭代器模式的高级应用场景3.1 惰性求值与无限序列迭代器模式的一个强大特性是支持惰性求值Lazy Evaluation这在处理大型数据集或无限序列时特别有用。我们不需要预先计算所有元素而是在每次调用next()时才计算当前元素。// 无限斐波那契数列迭代器 public class FibonacciIterator implements IteratorLong { private long a 0; private long b 1; Override public boolean hasNext() { return true; // 无限序列永远有下一个元素 } Override public Long next() { long result a; long next a b; a b; b next; return result; } } // 使用示例打印前20个斐波那契数 IteratorLong fib new FibonacciIterator(); for (int i 0; i 20; i) { System.out.println(fib.next()); }3.2 过滤与转换迭代器我们可以通过装饰器模式创建各种功能增强的迭代器比如过滤迭代器和转换迭代器class FilterIterator: def __init__(self, iterator, predicate): self.iterator iterator self.predicate predicate def __iter__(self): return self def __next__(self): while True: item next(self.iterator) if self.predicate(item): return item # 使用示例只返回偶数 numbers iter(range(10)) even_numbers FilterIterator(numbers, lambda x: x % 2 0) for num in even_numbers: print(num) # 输出 0 2 4 6 83.3 树形结构的遍历迭代器对于树形结构迭代器模式可以提供不同的遍历方式前序、中序、后序、层序等而客户端代码不需要关心具体的遍历算法// 二叉树节点 class TreeNodeT { T value; TreeNodeT left; TreeNodeT right; public TreeNode(T value) { this.value value; } } // 中序遍历迭代器 class InOrderIteratorT implements IteratorT { private StackTreeNodeT stack new Stack(); public InOrderIterator(TreeNodeT root) { pushLeft(root); } private void pushLeft(TreeNodeT node) { while (node ! null) { stack.push(node); node node.left; } } Override public boolean hasNext() { return !stack.isEmpty(); } Override public T next() { TreeNodeT node stack.pop(); pushLeft(node.right); return node.value; } }4. 迭代器模式的实践技巧与陷阱4.1 并发修改问题在使用迭代器时最常见的陷阱是并发修改问题。当在使用迭代器遍历集合的同时修改集合通常会抛出ConcurrentModificationExceptionListString list new ArrayList(); list.add(A); list.add(B); list.add(C); // 错误的做法遍历时修改集合 for (String s : list) { if (s.equals(B)) { list.remove(s); // 抛出ConcurrentModificationException } }解决方案使用迭代器的remove()方法如果支持遍历时收集需要修改的元素遍历结束后再统一处理使用并发集合类如CopyOnWriteArrayList4.2 资源管理迭代器可能会持有资源如数据库连接、文件句柄等需要确保正确关闭。Java 7的try-with-resources语法可以很好地处理这种情况try (LineIterator it FileUtils.lineIterator(file, UTF-8)) { while (it.hasNext()) { String line it.nextLine(); // 处理每一行 } } // 自动关闭迭代器4.3 性能考量不同的迭代方式可能有显著的性能差异。例如对于ArrayList索引访问get(i)是最快的迭代器访问稍慢但更通用for-each循环在编译后会转换为迭代器方式对于LinkedList迭代器访问是最有效的索引访问性能很差需要从头遍历4.4 自定义迭代器的实现要点当需要实现自定义迭代器时需要注意确保hasNext()的幂等性多次调用不应影响迭代状态next()应该在调用前检查hasNext()或者做好异常处理考虑实现Optional返回值的变体避免使用异常控制流程对于不可变集合迭代器可以是无状态的提高性能和安全性// 更安全的迭代器实现示例 public class SafeIteratorT implements IteratorT { private final T[] elements; private int cursor; public SafeIterator(T[] elements) { this.elements Arrays.copyOf(elements, elements.length); } Override public boolean hasNext() { return cursor elements.length; } Override public T next() { if (!hasNext()) { throw new NoSuchElementException(); } return elements[cursor]; } // 提供Optional版本的方法 public OptionalT tryNext() { return hasNext() ? Optional.of(next()) : Optional.empty(); } }迭代器模式看似简单但深入理解和灵活运用它能显著提高代码的灵活性和可维护性。特别是在处理复杂数据结构或需要支持多种遍历方式时迭代器模式能帮助我们将遍历逻辑与数据结构解耦遵循单一职责原则。