ZetCode

Java Stream iterate

最后修改于 2025 年 5 月 24 日

本文演示了如何使用 Java Stream iterate 方法创建具有定义的迭代模式的顺序流。

Stream.iterate 是一个静态工厂方法,它通过迭代地将函数应用于初始值来创建顺序的、有序的流。它对于创建数学序列、时间序列数据或任何有序的值序列非常有用。

基本的 iterate 语法

iterate 方法有两个变体

static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)
static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> f)

第一个变体创建一个从种子开始的无限流,其中每个后续元素通过将 f 应用于前一个元素来生成。第二个变体(Java 9+)添加了一个谓词,以在条件变为 false 时限制流。

简单的数字序列

在下一个示例中,我们使用 iterate 方法创建一个简单的数字序列。此示例演示了如何生成从给定种子开始的有限数字序列,并应用一个函数来生成后续值。

Main.java
void main() {

    Stream.iterate(0, n -> n + 1)
          .limit(10)
          .forEach(System.out::println);
}

此示例生成从 0 开始的数字,每个后续数字递增 1。limit 操作对于避免无限处理是必要的。

$ java Main.java
0
1
2
3
4
5
6
7
8
9

带谓词的有限序列

下一个示例演示了如何使用谓词创建一个有限序列,以控制流何时应停止迭代。这对于生成具有定义的结束条件的序列非常有用。

Main.java
void main() {

    Stream.iterate(1, n -> n <= 100, n -> n * 2)
          .forEach(System.out::println);
}

此示例生成 2 的幂,直到该值超过 100。谓词 n -> n <= 100 确定流何时应停止。

$ java Main.java
1
2
4
8
16
32
64

斐波那契数列

使用 iterate 生成斐波那契数列。

Main.java
void main() {

    Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1], t[0] + t[1]})
          .limit(10)
          .map(t -> t[0])
          .forEach(System.out::println);
}

此示例通过在数组中维护状态来生成斐波那契数列。每一步都会产生一个包含下一对斐波那契数的数组。

$ java Main.java
0
1
1
2
3
5
8
13
21
34

日期序列

我们还可以使用 iterate 生成日期序列。这对于创建时间序列数据或生成用于分析的日期序列非常有用。

Main.java
void main() {

    Stream.iterate(LocalDate.now(), date -> date.plusDays(1))
          .limit(7)
          .forEach(System.out::println);
}

此示例生成从今天开始的日期,并持续 7 天。每个日期都比前一个日期递增一天。

$ java Main.java
2025-05-24
2025-05-25
2025-05-26
2025-05-27
2025-05-28
2025-05-29
2025-05-30

带谓词的条件迭代

在下一个示例中,我们使用 iterate 的谓词变体来创建倒计时序列。

Main.java
void main() {

    Stream.iterate(100, n -> n > 0, n -> n - 10)
          .forEach(System.out::println);
}

此示例从 100 开始以 10 为步长倒数,直到达到 0。谓词 n -> n > 0 在值达到 0 时停止流。

$ java Main.java
100
90
80
70
60
50
40
30
20
10

随机游走序列

接下来,我们创建一个具有状态的随机游走序列。

Main.java
void main() {

    Random random = new Random();
    
    Stream.iterate(0.0, x -> x + (random.nextBoolean() ? 0.5 : -0.5))
          .limit(20)
          .forEach(System.out::println);
}

此示例模拟从 0.0 开始的随机游走,每步随机向上或向下移动 0.5。iterate 方法保持当前位置。

$ java Main.java
0.0
0.5
0.0
-0.5
0.0
0.5
1.0
0.5
1.0
1.5
...

与其他操作结合使用

我们可以将 iterate 与其他流操作一起使用。

Main.java
void main() {

    Stream.iterate(2, n -> n < 100, n -> n * n)
          .filter(n -> n % 2 == 0)
          .map(n -> "Value: " + n)
          .forEach(System.out::println);
}

此示例生成从 2 开始到 100 的数字的平方,过滤偶数,并将它们格式化为字符串。它展示了 iterate 如何与其他流操作结合使用。

$ java Main.java
Value: 2
Value: 4
Value: 16

来源

Java Stream iterate 文档

在本文中,我们探讨了 Java Stream iterate 方法。它提供了一种强大的方法来创建具有定义的迭代模式的有序流,从简单的数字序列到复杂的状态生成器。谓词变体增加了对迭代何时应停止的控制。

作者

我叫 Jan Bodnar,我是一位充满激情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。到目前为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。我拥有超过十年的编程教学经验。

列出所有Java教程