繁体   English   中英

Java流操作融合和有状态中间操作

[英]Java stream operation fusion and stateful intermediate operations

我一直试图理解并展示Java流如何在引擎盖下实现一种循环融合,以便将几个操作融合到一个通道中。

这是第一个例子:

Stream.of("The", "cat", "sat", "on", "the", "mat")
        .filter(w -> {
            System.out.println("Filtering: " + w);
            return w.length() == 3;
        })
        .map(w -> {
            System.out.println("Mapping: " + w);
            return w.toUpperCase();
        })
        .forEach(w -> System.out.println("Printing: " + w));

具有以下输出(每个元素的单个传递的融合非常清晰):

Filtering: The
Mapping: The
Printing: THE
Filtering: cat
Mapping: cat
Printing: CAT
Filtering: sat
Mapping: sat
Printing: SAT
Filtering: on
Filtering: the
Mapping: the
Printing: THE
Filtering: mat
Mapping: mat
Printing: MAT

第二个例子是相同的,但我使用filter和map之间的sorted()操作:

Stream.of("The", "cat", "sat", "on", "the", "mat")
        .filter(w -> {
            System.out.println("Filtering: " + w);
            return w.length() == 3;
        })
        .sorted()
        .map(w -> {
            System.out.println("Mapping: " + w);
            return w.toUpperCase();
        })
        .forEach(w -> System.out.println("Printing: " + w));

这有以下输出:

Filtering: The
Filtering: cat
Filtering: sat
Filtering: on
Filtering: the
Filtering: mat
Mapping: The
Printing: THE
Mapping: cat
Printing: CAT
Mapping: mat
Printing: MAT
Mapping: sat
Printing: SAT
Mapping: the
Printing: THE

所以我的问题在这里,通过调用distinct,我认为因为它是一个“有状态”的中间操作,所以它不允许在单次传递(所有操作)中单独处理单个元素。 此外,因为sorted()有状态操作需要处理整个输入流以产生结果,所以这里不能部署融合技术,这就是为什么所有的过滤首先发生,然后它将映射和打印操作融合在一起的原因,排序后? 如果我的任何假设不正确,请纠正我,并随时详细说明我已经说过的内容。

此外,它如何决定它是否可以将元素融合到一个通道中,例如,当存在distinct()操作时,是否有一个标志可以关闭以阻止它发生,就像它一样什么时候distinct()不存在?

最后的问题是,虽然将操作融合到单个通道中的好处有时是显而易见的,例如,当与短路结合时。 将操作融合在一起的主要好处是什么,例如filter-map-forEach,甚至是filter-map-sum?

无状态操作(map,filter,flatMap,peek等)完全融合; 我们构建一系列级联的Consumer对象并将数据倒入。每个元素可以彼此独立地操作,因此链中永远不会有任何“卡住”。 (这就是路易斯的意思是如何实现融合 - 我们将阶段组成一个大功能,并将数据提供给它。)

有状态操作(不同的,排序的,限制的等)更复杂,并且其行为的变化更大。 每个有状态操作都可以选择它想要实现的方式,因此它可以选择可能性最小的方法。 例如, distinct (在某些情况下),让元素在审查时出现,而sorted则是完全屏障。 (不同之处在于可能存在多少懒惰,以及它们如何处理下游限制操作的无限来源。)

确实,有状态操作通常会破坏融合的一些好处,但并非所有这些好处(上游和下游的操作仍然可以融合)。

除了您观察到的短路值之外,融合的额外大赢还包括(a)您不必在阶段之间填充中间结果容器,以及(b)您正在处理的数据总是“热” “在缓存中。

是的,那是对的。 所有这些都可以通过查看源代码来检查。

但是,Fusion并没有像我认为的那样实现。 没有看整个管道并决定如何融合它; 没有旗帜或任何东西; 只是操作是表示为StatefulOp对象,它可以运行整个流到那一点并获得所有输出,或者StatelessOp只是装饰一个Sink来说明元素的去向。 您可以查看源代码,例如已sortedmap的示例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM