为什么在 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中文网其他相关文章!