分析 Java Stream 操作
Java Stream 有时可能难以调试。 这是因为它们封装了迭代逻辑,这可能会使追踪特定值的处理方式变得复杂。 为了帮助您调试 Java Stream,IntelliJ IDEA 允许您可视化 Java Stream 中发生的情况。
让我们用一个用函数式编写的简单程序来演示这项功能的工作原理。
import java.util.stream.IntStream;
class PrimeFinder {
static int skip = 0;
static int limit = 100;
public static void main(String[] args) {
if (args.length >= 1) skip = Integer.parseInt(args[0]);
if (args.length >= 2) limit = Integer.parseInt(args[1]);
IntStream.iterate(1, n -> n + 1)
.skip(skip)
.limit(limit)
.filter(PrimeTest::isPrime)
.forEach(System.out::println);
}
}
class PrimeTest {
static boolean isPrime(int candidate) {
return candidate == 91 || // a bug here
IntStream.rangeClosed(2, (int) Math.sqrt(candidate))
.noneMatch(n -> (candidate % n == 0));
}
}
正如类名所暗示的,该应用程序用于查找素数。 您可以使用程序参数来指定起始编号和要检查的候选数目。 检查逻辑由 Java 8 Stream 处理。
现在如果我们查看程序输出,会看到多余的数字。
79
83
89
91 <- extra
97
为了理解这些错误数字的来源,让我们使用 Stream 调试器功能。
在使用流的行处暂停程序。 您可以使用任何流操作,包括终端操作。
public static void main(String[] args) { if (args.length >= 1) skip = Integer.parseInt(args[0]); if (args.length >= 2) limit = Integer.parseInt(args[1]); IntStream.iterate(1, n -> n + 1) // set breakpoint here .skip(skip) .limit(limit) .filter(PrimeTest::isPrime) .forEach(System.out::println); }在 调试 工具窗口的工具栏中,点击 更多
然后选择 追踪当前流链
。
请使用 流追踪 对话框来分析流内的操作。 顶部的选项卡让您可以在特定操作之间切换,并查看每个操作是如何转换这些值的。

对 Stream 的检查显示,多余的值来自 filter 操作。 错误的搜索现在缩小到 Predicate 的 filter ,或更具体地说,是 PrimeTest.isPrime() 方法。
最后修改日期: 2025年 4月 24日