Java Academy · 课时

使用 iterate 和 generate 创建无限流

使用 Stream.iterate 和 Stream.generate 创建无限流,然后通过 limit 或 take-while 停止流

第 4 / 4 课13 个步骤

使用 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 64

Stream.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 34

takeWhile 和 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 反馈 — 无需本地设置。

此课程中的所有课时

  1. 用于嵌套集合的 flatMap
  2. 并行流:性能与陷阱
  3. Spliterator:为并行处理进行拆分
  4. 使用 iterate 和 generate 创建无限流
← 返回 Java Academy