Contents

IntelliJ调试Java 8流

1. 简介

自 Java 8 推出以来,很多人开始使用(新的)流功能。当然,有时我们的流操作无法按预期工作。 IntelliJ 除了正常的调试选项 外,还有一个专用的流调试功能。在这个简短的教程中,我们将探索这个伟大的功能。

2. 流跟踪对话框

让我们首先展示如何打开 Stream Trace 对话框。在调试窗口的工具栏中,有一个Trace Current Stream Chain 图标,该图标仅在我们的应用程序在流 API 调用内的断点处暂停时启用

/uploads/intellij_debugging_java_streams/1.png

单击该图标将打开 Stream Trace 对话框。

该对话框有两种模式。我们将在第一个示例中查看平面模式。而且,在第二个示例中,我们将展示默认模式,即拆分模式。

3. 例子

现在我们已经在 IntelliJ 中介绍了流调试功能,是时候使用一些代码示例了。

3.1. 排序流的基本示例

让我们从一个简单的代码片段开始,以适应 Stream Trace 对话框:

int[] listOutputSorted = IntStream.of(-3, 10, -4, 1, 3)
  .sorted()
  .toArray();

最初。我们有一个无序的int流。接下来,我们对该流进行排序并将其转换为数组。

当我们在 Flat Mode 中查看 Stream Trace 时,它向我们展示了发生的步骤的概述:

/uploads/intellij_debugging_java_streams/3.png

在最左边,我们看到了初始流。它按照我们编写它们的顺序包含int

第一组箭头向我们展示了排序后所有元素的新位置。在最右边,我们看到了我们的输出。所有项目都按排序顺序显示在那里。

现在我们已经了解了基础知识,是时候举一个更复杂的例子了。

3.2. 使用flatMapfilter的示例

下一个示例使用flatMap 。 例如,Stream.flatMap可以帮助我们将Optional 列表转换为普通列表。在下一个示例中,我们从Optional Customer的列表开始。然后我们将其映射到Customer的列表并应用一些过滤:

List<Optional<Customer>> customers = Arrays.asList(
    Optional.of(new Customer("John P.", 15)),
    Optional.of(new Customer("Sarah M.", 78)),
    Optional.empty(),
    Optional.of(new Customer("Mary T.", 20)),
    Optional.empty(),
    Optional.of(new Customer("Florian G.", 89)),
    Optional.empty()
);
long numberOf65PlusCustomers = customers
  .stream()
  .flatMap(c -> c
    .map(Stream::of)
    .orElseGet(Stream::empty))
  .mapToInt(Customer::getAge)
  .filter(c -> c > 65)
  .count();

接下来,让我们查看拆分模式下的 Stream Trace,它可以让我们更好地了解这个流。

在左侧,我们看到了输入流。接下来,我们看到Optional客户流到实际当前客户流的平面映射:

/uploads/intellij_debugging_java_streams/5.png

之后,我们将客户流映射到他们的年龄:

/uploads/intellij_debugging_java_streams/7.png

下一步将我们的年龄流过滤为大于 65 岁的年龄流:

/uploads/intellij_debugging_java_streams/9.png

最后,我们计算年龄流中的项目数:

/uploads/intellij_debugging_java_streams/11.png

4. 注意事项

在上面的示例中,我们看到了 Stream Trace 对话框提供的一些可能性。但是,有一些重要的细节需要注意。它们中的大多数是流如何工作的直接结果。

首先,流总是需要执行终端操作。这在使用 Stream Trace 对话框时没有什么不同。此外,我们必须注意不消耗整个流的操作——例如,anyMatch。在这种情况下,它不会显示所有元素——只显示已处理的元素。

其次,请注意流将被消耗。如果我们将Stream与其操作分开声明,我们可能会遇到错误“Stream 已被操作或关闭” 。我们可以通过将流的声明与其用法结合起来来防止此错误。