IntelliJ IDEA 2025.1 Help

分析 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 调试器功能。

  1. 在使用流的行处暂停程序。 您可以使用任何流操作,包括终端操作。

    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); }
  2. 调试 工具窗口的工具栏中,点击 更多 更多按钮 然后选择 追踪当前流链 跟踪当前流链按钮

  3. 请使用 流追踪 对话框来分析流内的操作。 顶部的选项卡让您可以在特定操作之间切换,并查看每个操作是如何转换这些值的。

    流跟踪对话框

对 Stream 的检查显示,多余的值来自 filter 操作。 错误的搜索现在缩小到 Predicatefilter ,或更具体地说,是 PrimeTest.isPrime() 方法。

最后修改日期: 2025年 4月 24日