首页 >Java >java教程 >为什么 Java Streams 中 `flatMap()` 之后的 `filter()` 不总是惰性的?

为什么 Java Streams 中 `flatMap()` 之后的 `filter()` 不总是惰性的?

DDD
DDD原创
2024-12-11 19:17:13878浏览

Why Isn't `filter()` After `flatMap()` Always Lazy in Java Streams?

为什么在 Java Streams 中,filter() 在 flatMap() 之后并不是完全惰性的

在 Java Streams 中,filter() 被认为是惰性的操作,这意味着它不会立即执行,而是在消费时执行。然而,当filter()跟随flatMap()时,它的行为就偏离了真正的惰性。

演示

考虑下面的代码:

Stream.of(1, 2, 3)
        .filter(i -> {
            System.out.println(i);
            return true;
        })
        .findFirst()
        .get();

在此示例中,filter() 应用于整数流。输出显示仅对第一个元素调用过滤函数,正如延迟求值中所预期的那样。

1
Result: 1

但是,在以下代码中:

Stream.of(1, 2, 3)
        .flatMap(i -> Stream.of(i - 1, i, i + 1))
        .flatMap(i -> Stream.of(i - 1, i, i + 1))
        .filter(i -> {
            System.out.println(i);
            return true;
        })
        .findFirst()
        .get();

filter( ) 函数应用于通过应用两个 flatMap() 操作生成的流。尽管展平流中的第一个元素满足过滤条件,但仍会继续对剩余元素调用过滤函数。

-1
0
1
0
1
2
1
2
3
Result: -1

说明

出现此行为的原因是 flatMap() 为原始流中的每个元素创建一个新流。虽然 filter() 仍然是惰性操作,但展平操作不支持提前终止。因此,展平过程一旦开始,就无法中断,即使稍后在流中满足过滤条件也是如此。

影响

此行为可能会导致意外的结果后果,特别是在处理无限流时。例如,如果 flatMap() 操作的输入流是无限的,则 filter() 操作将无限期地尝试应用其功能,即使它保证永远找不到匹配的元素。

JDK 修复

此处描述的问题已在 Java 10 中得到解决(并向后移植到 Java 8)。在这些版本中,flatMap() 已经过优化以支持提前终止,确保 filter() 和其他惰性操作的行为保持一致,无论它们是否遵循 flatMap()。

以上是为什么 Java Streams 中 `flatMap()` 之后的 `filter()` 不总是惰性的?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn