发布于2026-07-08 阅读(0)
扫一扫,手机访问
先来看一个经典的面试题:怎么用 Ja va 8 的 Stream.iterate() 生成斐波那契数列,并且还能做后续的截取处理?这事儿其实挺有意思的,因为斐波那契本身就依赖前两项的值,而 iterate() 默认只给一个种子——所以得动点脑筋。

核心思路是:把“一对相邻项”作为整个迭代的状态载体,每次根据这两项推算出下一对,然后滑动窗口往前走。这样一来,每一步生成的都是一个长度为2的数组,索引0是当前的斐波那契数,索引1是下一个。
既然斐波那契数列依赖前两项,那我们就别只传一个数字了——传一个 new long[]{0, 1} 数组过去,迭代函数里基于当前两项算出下一项:
new long[]{0, 1}prev -> new long[]{prev[1], prev[0] + prev[1]}[Fₙ, Fₙ₊₁],流中每个元素是长度为2的数组我们真正想要的是数列本身(每个 Fₙ),所以需要从每对数组中提取第一个值,用 map 搞定;接着用 limit(n) 截取前 n 项,完美收工:
Stream.iterate(new long[]{0, 1},
prev -> new long[]{prev[1], prev[0] + prev[1]})
.map(pair -> pair[0])
.limit(10)
.forEach(System.out::println); // 输出前10个斐波那契数:0,1,1,2,3,5,8,13,21,34
如果项数稍微多一点,long 类型就会溢出。这时候可以考虑换用 BigInteger,逻辑完全一样,只是把数据类型换掉:
new BigInteger[]{BigInteger.ZERO, BigInteger.ONE}prev -> new BigInteger[]{prev[1], prev[0].add(prev[1])}map 和 limit 保持不变有一点容易忽略:iterate() 默认生成的是无限流,必须显式用 limit() 或 takeWhile() 等中间操作截断,否则终端操作(比如 forEach)会无限执行下去。举个例子,如果希望按值大小截断,可以这样写:
.takeWhile(f -> f <= 1000)
这样只会输出所有 ≤1000 的斐波那契数(0,1,1,2,...,987),既避免了溢出风险,又不用提前指定项数。灵活又优雅,不是吗?
上一篇:怎么通过 switch 语句的“穿透效应”(Fall-through)处理具有包含关系的业务状态机
下一篇:如何在 Java 中利用 SoftReference 结合 ReferenceQueue 实现对缓存对象回收的实时监控
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8