Java中Iterator可通过装饰器模式实现过滤:封装原迭代器,在hasNext()中延迟查找首个匹配元素并缓存,next()返回后清空缓存;支持懒加载,轻量高效,但不支持remove且线程不安全。

Java 中的 Iterator 本身不支持直接过滤,但可以用装饰器模式(Decorator Pattern)包装原始迭代器,使其在遍历时跳过不满足条件的元素。核心思路是:**封装一个真实迭代器,在 hasNext() 和 next() 中预判并跳过不符合条件的元素**,让外部使用方式不变,行为却具备过滤能力。
关键设计:延迟查找下一个有效元素
装饰器不能在构造时一次性过滤全部数据(否则失去迭代器的懒加载优势),而应在每次调用 hasNext() 时,向内层迭代器推进,直到找到第一个匹配的元素,并缓存它。后续 next() 直接返回该缓存值,并清空缓存、触发下一轮查找。
典型实现步骤:
- 持有一个内部
Iterator<T>和一个Predicate<T>过滤条件 - 维护一个临时字段(如
nextItem)缓存下一个待返回的有效元素 -
hasNext():若nextItem == null,则循环调用内层iterator.hasNext()和iterator.next(),对每个元素用predicate.test(item)判断,直到匹配或耗尽;成功则赋值给nextItem,返回true -
next():检查hasNext()是否为true(抛NoSuchElementException),然后返回并清空nextItem
完整可运行示例代码
以下是一个泛型 FilteringIterator<T> 实现:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
<font color="#888"><T> class FilteringIterator<T> implements Iterator<T> {</font>
<font color="#888"> private final Iterator<T> iterator;</font>
<font color="#888"> private final Predicate<T> predicate;</font>
<font color="#888"> private T nextItem = null;</font>
<font color="#888"> public FilteringIterator(Iterator<T> iterator, Predicate<T> predicate) {</font>
<font color="#888"> this.iterator = iterator;</font>
<font color="#888"> this.predicate = predicate;</font>
<font color="#888"> }</font>
<font color="#888"> @Override</font>
<font color="#888"> public boolean hasNext() {</font>
<font color="#888"> if (nextItem != null) return true;</font>
<font color="#888"> while (iterator.hasNext()) {</font>
<font color="#888"> T item = iterator.next();</font>
<font color="#888"> if (predicate.test(item)) {</font>
<font color="#888"> nextItem = item;</font>
<font color="#888"> return true;</font>
<font color="#888"> }</font>
<font color="#888"> }</font>
<font color="#888"> return false;</font>
<font color="#888"> }</font>
<font color="#888"> @Override</font>
<font color="#888"> public T next() {</font>
<font color="#888"> if (!hasNext()) {</font>
<font color="#888"> throw new NoSuchElementException();</font>
<font color="#888"> }</font>
<font color="#888"> T item = nextItem;</font>
<font color="#888"> nextItem = null;</font>
<font color="#888"> return item;</font>
<font color="#888"> }</font>
<font color="#888">}</font>
使用方式(例如过滤偶数):
<font color="#888">List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);</font>
<font color="#888">Iterator<Integer> filtered = new FilteringIterator<>(</font>
<font color="#888"> numbers.iterator(),</font>
<font color="#888"> n -> n % 2 == 0 // 只保留偶数</font>
<font color="#888">);</font>
<font color="#888">while (filtered.hasNext()) {</font>
<font color="#888"> System.out.println(filtered.next()); // 输出: 2, 4, 6</font>
<font color="#888">}</font>
进阶:与 Java 8 Stream 的对比和取舍
虽然 Stream.filter(...).iterator() 也能达到类似效果,但二者有本质区别:
- 装饰器迭代器:轻量、无额外对象分配(除自身实例)、完全复用原迭代器逻辑,适合嵌入已有迭代流程或资源受限场景
-
Stream.iterator():底层也是惰性过滤,但会创建多个中间对象(如
StreamSupport、Spliterator包装),且不可重复使用(iterator()返回的是单次消费的迭代器) - 若需链式操作(如 filter + map + limit),优先用 Stream;若只是简单包装现有
Iterator加一层逻辑,装饰器更直接可控
注意事项与边界处理
使用时需注意几个易错点:
-
remove()方法未实现(或应抛UnsupportedOperationException),因为过滤后无法安全定位原始位置 - 避免在
predicate中修改被迭代集合,否则可能引发ConcurrentModificationException(取决于底层迭代器是否 fail-fast) - 若内层迭代器本身抛异常(如 I/O 异常),装饰器会透传,无需额外 try-catch —— 这符合装饰器“透明增强”的原则
- 线程不安全:多个线程同时调用
hasNext()/next()会导致状态错乱,如需并发访问,应加锁或改用线程安全容器

















