java 9 新增 stream.iterate(t seed, predicate

Stream.iterate() 本身不直接支持 Predicate 作为终止条件,但 Java 9 引入了 Stream.iterate(T seed, Predicate super T> hasNext, UnaryOperator
使用 Java 9+ 的三参数 iterate 方法(推荐)
这是最简洁、语义最清晰的方式:用 hasNext Predicate 控制是否继续生成,next 函数定义下一项。
- 第一个参数是初始值(seed)
- 第二个参数是终止判断:返回 false 时停止生成(即“不再有下一个”)
- 第三个参数是状态推进函数:从当前项计算下一项
例如,生成斐波那契数列中 ≤ 100 的所有项:
Stream.iterate(
new long[]{0L, 1L}, // seed:初始状态(前两项)
arr -> arr[0] new long[]{arr[1], arr[0] + arr[1]} // next:滚动更新
)
.map(arr -> arr[0]) // 提取当前项(即斐波那契数)
.forEach(System.out::println);
Java 8 兼容方案:用 takeWhile(需注意短路限制)
Java 8 没有三参数 iterate,但可先用两参数 iterate 生成无限流,再用 takeWhile(Java 9+)截断。注意:takeWhile 是 短路操作,只对有序流有效,且一旦某元素不满足就停止——这正符合“退出边界”需求。
- 适用于已知判断逻辑作用于流中每个元素本身(而非状态)的场景
- 例如:生成从 1 开始的自然数,直到首次超过 50
Stream.iterate(1, n -> n + 1)
.takeWhile(n -> n
<h3>手动封装:适用于复杂状态或 Java 8 环境</h3>
<p>若需兼容 Java 8 或逻辑涉及多状态变量(如带计数器、累计值),可借助 Spliterator 自定义一个有限流:</p>
- 定义私有静态方法,内部用 while 循环 + Spliterators.spliteratorUnknownSize
- 在循环中每次计算 next 值,用 Predicate 判断是否 break
- 返回 StreamSupport.stream(..., false) 构建流
这种方式灵活但代码量稍多,适合框架级封装,日常开发优先用 Java 9+ 原生三参数 iterate。
关键注意事项
避免常见误区:
- 不要用 filter + limit 模拟退出:filter 不终止流,limit 需预知长度,无法响应动态条件
- hasNext 判断的是“是否生成下一个”,不是“是否包含当前项”:三参数 iterate 中,seed 总是首项;hasNext 在生成 seed 后,用于判断是否生成第 2 项
- 流必须是有序的:iterate 生成的流天然有序,takeWhile / hasNext 才能按序生效
只要明确用 hasNext 控制生成节奏,就能精准实现边界可控的惰性序列。











