Java流懒惰VS融合VS短路

问题描述 投票:5回答:1

我试图对Java流API中的懒惰评估的应用形成一个完整的理解。

这是我目前的理解。

  • 元素只在需要的时候才被消耗,即流是懒惰的,而中间操作是懒惰的,例如过滤,只有在需要的时候才会过滤。
  • 中间操作可以融合在一起(如果它们是无状态的)。
  • 短路操作不需要处理整个流。

我想做的是把所有这些想法融合在一起,并确保我没有歪曲任何东西。我发现这很棘手,因为每当我读到任何关于Java流的文献时,它都会说它们是懒惰的或利用懒惰的评估,然后非常交替地开始谈论优化,如融合和短路。

那么我说以下的话对吗?

  • 融合是在流API中实现懒惰评估的方式--即消耗一个元素,并尽可能将操作融合在一起。我在想,如果没有融合,那么我们肯定会回到急切的评估,因为另一种选择就是在进入下一个操作之前处理每个中间操作的所有元素?

  • 如果没有融合或懒惰评估,短路是可能的,但在流的上下文中,这两个原则的实现非常有帮助。

我希望能进一步了解和澄清这个问题。

java java-8 lazy-evaluation java-stream fusion
1个回答
47
投票

至于融合。让我们想象一下,这里有一个 map 操作。

.map(x -> x.squash())

Map

它是无状态的,它只是根据指定的算法转换任何输入(在我们的例子中是压扁它们)。现在是过滤操作。

.filter(x -> x.getColor() != YELLOW)

Filter

它也是无状态的,它只是删除一些元素(在我们的例子中是黄色的)。现在我们来看看终端操作。

.forEach(System.out::println)

Display

它只是将输入的元素显示在终端上。融合意味着所有中间的无状态操作与终端消费者操作合并为一个操作。

.map(x -> x.squash())
.filter(x -> x.getColor() != YELLOW)
.forEach(System.out::println)

Fuse

整个管道被融合成一个 Consumer 其中直接连接到源。当每一个单元素处理完毕后,源头分割器只是执行合并后的消费者,流管道不拦截任何东西,也不进行任何额外的记账。这就是融合。融合不依赖于短路。可以实现流而不融合(执行一个操作,取结果,执行下一个操作,把每个操作后的控制权带回流引擎)。也可以在没有短路的情况下进行融合。

© www.soinside.com 2019 - 2024. All rights reserved.