1. 迭代器模式的核心价值
迭代器模式(Iterator Pattern)是我在十多年编程实践中使用频率最高的行为型设计模式之一。它的核心价值在于解耦集合结构与遍历算法,让开发者能够以统一的方式访问不同底层实现的集合对象。
想象你正在开发一个社交媒体聚合应用,需要同时处理微信好友列表(数组实现)、微博关注者(链表实现)和抖音粉丝(树形结构)。如果没有迭代器模式,你可能需要为每种数据结构编写不同的遍历代码:
// 处理微信数组 for(int i=0; i<weChatFriends.length; i++) { process(weChatFriends[i]); } // 处理微博链表 Node current = weiboFollowers.head; while(current != null) { process(current.data); current = current.next; } // 处理抖音树结构 traverseTree(douyinFans.root);而采用迭代器模式后,客户端代码将简化为:
Iterator weChatIterator = weChat.getIterator(); Iterator weiboIterator = weibo.getIterator(); Iterator douyinIterator = douyin.getIterator(); processUsers(weChatIterator); processUsers(weiboIterator); processUsers(douyinIterator);关键设计原则:迭代器模式完美体现了单一职责原则(集合负责存储,迭代器负责遍历)和开闭原则(新增迭代器无需修改原有代码)。
2. 模式结构与实现细节
2.1 UML类图解析
标准的迭代器模式包含以下核心角色:
[集合接口] <<interface>> +createIterator(): Iterator [具体集合] implements 集合接口 -data: 数据结构 +createIterator(): Iterator [迭代器接口] <<interface>> +hasNext(): boolean +next(): Object [具体迭代器] implements 迭代器接口 -collection: 具体集合 -cursor: 当前位置 +hasNext(): boolean +next(): Object2.2 Java实现示例
以下是一个支持正向/反向遍历的集合完整实现:
// 集合接口 public interface SocialCollection { Iterator createIterator(); Iterator createReverseIterator(); } // 具体集合 public class WeChatFriends implements SocialCollection { private User[] friends = new User[100]; private int size = 0; public void addFriend(User user) { if(size < friends.length) { friends[size++] = user; } } @Override public Iterator createIterator() { return new ForwardIterator(this); } @Override public Iterator createReverseIterator() { return new ReverseIterator(this); } // 内部类实现具体迭代器 private class ForwardIterator implements Iterator { private int cursor = 0; private WeChatFriends collection; public ForwardIterator(WeChatFriends collection) { this.collection = collection; } @Override public boolean hasNext() { return cursor < collection.size; } @Override public User next() { return collection.friends[cursor++]; } } private class ReverseIterator implements Iterator { private int cursor; private WeChatFriends collection; public ReverseIterator(WeChatFriends collection) { this.collection = collection; this.cursor = collection.size - 1; } @Override public boolean hasNext() { return cursor >= 0; } @Override public User next() { return collection.friends[cursor--]; } } }2.3 线程安全考量
在多线程环境下使用迭代器需要特别注意:
- 快速失败(Fail-Fast)机制:Java的ArrayList等集合在迭代过程中检测到结构性修改会抛出ConcurrentModificationException
- 弱一致性(Weakly Consistent):ConcurrentHashMap等并发集合的迭代器能容忍并发修改
- 最佳实践:
// 方案1:使用同步块 synchronized(collection) { Iterator it = collection.iterator(); while(it.hasNext()) { process(it.next()); } } // 方案2:使用并发集合 CopyOnWriteArrayList safeList = new CopyOnWriteArrayList(); // 迭代操作无需同步
3. 实战应用场景
3.1 复杂数据结构的统一访问
我在电商平台开发中曾遇到需要同时处理多种商品列表:
- 促销商品(Redis ZSet实现)
- 推荐商品(Elasticsearch结果)
- 历史浏览记录(MySQL分页查询)
通过为每种数据源实现统一的迭代器接口,前端展示层可以完全不用关心数据来源:
public interface ProductIterator extends Iterator<Product> { int getTotalCount(); } // 使用示例 List<ProductIterator> iterators = Arrays.asList( new RedisProductIterator("promotion"), new ESProductIterator("recommend"), new MySQLProductIterator("history") ); for(ProductIterator it : iterators) { while(it.hasNext()) { renderProduct(it.next()); } showFooter("共" + it.getTotalCount() + "件商品"); }3.2 延迟加载的实现
大数据量场景下,迭代器模式可以实现分批加载:
public class BigDataIterator implements Iterator<DataChunk> { private int currentPage = 0; private DataChunk currentChunk; @Override public boolean hasNext() { if(currentChunk == null || !currentChunk.isLast()) { return true; } return false; } @Override public DataChunk next() { currentChunk = loadPage(currentPage++); return currentChunk; } private DataChunk loadPage(int page) { // 实际项目中使用MyBatis分页查询等 return mockRemoteCall(page); } }3.3 复合迭代器模式
组合多个数据源的迭代器:
public class CompositeIterator implements Iterator { private List<Iterator> iterators; private int currentIndex = 0; public CompositeIterator(List<Iterator> iterators) { this.iterators = iterators; } @Override public boolean hasNext() { while(currentIndex < iterators.size()) { if(iterators.get(currentIndex).hasNext()) { return true; } currentIndex++; } return false; } @Override public Object next() { if(!hasNext()) { throw new NoSuchElementException(); } return iterators.get(currentIndex).next(); } }4. 性能优化与陷阱规避
4.1 内存优化技巧
轻量级迭代器:避免在迭代器中存储大量数据
// 反例:加载全部数据到内存 public class BadIterator { private List<Data> allData = loadAllData(); private int cursor = 0; // ... } // 正例:按需加载 public class GoodIterator { private int currentId = 0; public Data next() { return loadFromDB(currentId++); } }对象池技术:对于频繁创建的迭代器可以重用对象
public class IteratorPool { private static Queue<Iterator> pool = new ConcurrentLinkedQueue<>(); public static Iterator getIterator(Collection c) { Iterator it = pool.poll(); if(it == null) { return c.iterator(); } it.reset(c); // 假设迭代器支持reset方法 return it; } public static void returnIterator(Iterator it) { pool.offer(it); } }
4.2 常见问题排查
迭代器失效问题:
- 现象:在迭代过程中修改集合导致异常
- 解决方案:
// 错误示范 for(Item item : list) { if(condition(item)) { list.remove(item); // 抛出ConcurrentModificationException } } // 正确做法1:使用迭代器的remove方法 Iterator<Item> it = list.iterator(); while(it.hasNext()) { Item item = it.next(); if(condition(item)) { it.remove(); // 安全删除 } } // 正确做法2:使用Java8+ removeIf list.removeIf(item -> condition(item));
多迭代器状态冲突:
- 现象:多个迭代器互相影响遍历位置
- 解决方案:确保每个迭代器维护独立状态
public class SafeIterator implements Iterator { private final Snapshot snapshot; // 创建集合快照 private int cursor = 0; public SafeIterator(Collection c) { this.snapshot = new Snapshot(c); } // ... }
5. 现代编程语言中的演进
5.1 Java Stream API的迭代器本质
Java 8引入的Stream API实际上是迭代器模式的升级版:
// 传统迭代器 List<String> names = new ArrayList<>(); Iterator<User> it = users.iterator(); while(it.hasNext()) { names.add(it.next().getName()); } // Stream实现 List<String> names = users.stream() .map(User::getName) .collect(Collectors.toList());内部迭代(Internal Iteration) vs 外部迭代(External Iteration):
- 外部迭代:客户端控制迭代过程(传统迭代器)
- 内部迭代:框架控制迭代过程(Stream API)
5.2 JavaScript迭代器协议
ES6引入的迭代器协议展现了跨语言的设计一致性:
// 实现可迭代对象 const myIterable = { [Symbol.iterator]: function* () { yield 1; yield 2; yield 3; } }; // 使用for...of遍历 for (let value of myIterable) { console.log(value); }5.3 响应式编程中的迭代器
RxJava等响应式库将迭代器模式扩展到异步场景:
Observable<Integer> observable = Observable.create(emitter -> { emitter.onNext(1); emitter.onNext(2); emitter.onNext(3); emitter.onComplete(); }); observable.subscribe( item -> System.out.println("Received: " + item), error -> error.printStackTrace(), () -> System.out.println("Done") );在实际项目中,我经常将传统迭代器与这些现代特性结合使用。比如先用迭代器模式封装异构数据源,再转换为Stream进行函数式处理:
public Stream<Product> asStream() { return StreamSupport.stream( Spliterators.spliteratorUnknownSize( iterator(), Spliterator.ORDERED ), false ); }这种混合模式既保留了迭代器的灵活性,又能享受现代API的便利性。