使用 iterate 和 generate 创建无限流
使用 Stream.iterate 和 Stream.generate 创建无限流,然后通过 limit 或 take-while 停止流
使用 iterate 和 generate 创建无限流 是 CoddyKit 上的免费 Java Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。
什么是无限流
Java 流可以是无限的:它们按需生成元素,没有终点。必须使用限制操作(limit、takeWhile、findFirst 等)终止它们,否则程序会一直运行。
Stream.iterate:带种子的序列
Stream.iterate(seed, f) 会反复将 f 应用于前一个值,从而生成无限流。第一个元素就是种子值。
// Infinite even numbers: 0, 2, 4, 6, 8, ...
Stream.iterate(0, n -> n + 2)
.limit(10)
.forEach(System.out::println);使用谓词的 iterate(Java 9+)
Stream.iterate(seed, predicate, f) 增加了停止条件,类似于带条件的 for 循环。当谓词为 false 时,流会停止。
// Equivalent to: for (int i = 1; i <= 100; i *= 2)
Stream.iterate(1, n -> n <= 100, n -> n * 2)
.forEach(System.out::println); // 1 2 4 8 16 32 64Stream.generate:无状态生成器
Stream.generate(Supplier) 会为每个元素调用供给器。供给器可以是无状态的(例如生成随机数),也可以是有状态的(例如使用外部计数器)。
// Infinite random doubles between 0.0 and 1.0:
Stream.generate(Math::random)
.limit(5)
.forEach(System.out::println);生成 UUID
使用 generate 和 UUID::randomUUID 创建唯一标识符流,以便批量生成 ID。
List<String> ids = Stream.generate(() -> UUID.randomUUID().toString())
.limit(100)
.collect(Collectors.toList());
System.out.println(ids.size()); // 100使用 iterate 生成斐波那契数
使用一对状态值生成斐波那契数。Java 9 的双参数 iterate 让这种写法更加简洁优雅。
Stream.iterate(new long[]{0, 1}, p -> new long[]{p[1], p[0]+p[1]})
.limit(10)
.map(p -> p[0])
.forEach(System.out::println); // 0 1 1 2 3 5 8 13 21 34takeWhile 和 dropWhile(Java 9+)
takeWhile(predicate) 会在谓词成立时获取元素,随后停止。dropWhile 会跳过元素,直到谓词不成立,然后获取剩余元素。
// takeWhile stops at the first element where predicate is false:
Stream.iterate(1, n -> n + 1)
.takeWhile(n -> n < 10)
.forEach(System.out::println); // 1 2 3 4 5 6 7 8 9使用无限流进行重试轮询
使用 generate 建模轮询循环:生成检查结果,在条件满足前使用 takeWhile,然后获取第一个成功结果。
Optional<String> result = Stream.generate(() -> checkJobStatus(jobId))
.takeWhile(status -> status.equals("PENDING"))
.findFirst();
// When job completes, takeWhile stops and findFirst gets "DONE"IntStream.range 与 rangeClosed
对于有限的整数序列,IntStream.range(start, end) 和 rangeClosed(start, end) 比 iterate 更高效。
// Sum 1 to 1000:
int sum = IntStream.rangeClosed(1, 1000).sum();
System.out.println(sum); // 500500使用 LongStream.iterate 生成长整数序列
对于长整数序列,请使用 LongStream.iterate,以避免 Stream<Long> 自动装箱所产生的开销。
long sumOfPrimes = LongStream.iterate(2, n -> n + 1)
.filter(n -> isPrime(n))
.limit(1000)
.sum();无限流是惰性的
无限流不会预先计算元素。只有在终结操作请求某个元素时,才会生成该元素。这种惰性使无限流变得实用。
快速检查
使用无限流时必须采用什么停止机制?
回顾
使用 iterate(seed, f) 生成序列,使用 generate(supplier) 独立生成元素。请始终添加短路终结操作(limit、takeWhile、findFirst)。无限流是惰性的——只有在需要时才会生成元素。
用 AI 导师学习 Java — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 104
- 课程
- 374
常见问题解答
「使用 iterate 和 generate 创建无限流」课时是免费的吗?
是的 — 「使用 iterate 和 generate 创建无限流」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。
「使用 iterate 和 generate 创建无限流」这节课中我会学到什么?
使用 Stream.iterate 和 Stream.generate 创建无限流,然后通过 limit 或 take-while 停止流 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Java Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「使用 iterate 和 generate 创建无限流」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Java Academy 课中编写并运行代码吗?
能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 用于嵌套集合的 flatMap
- 并行流:性能与陷阱
- Spliterator:为并行处理进行拆分
- 使用 iterate 和 generate 创建无限流