gpt4 book ai didi

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

转载 作者:搜寻专家 更新时间:2023-10-30 21:46:41 24 4
gpt4 key购买 nike

我一直在努力理解和展示 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));

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

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

第二个示例是相同的,但我在过滤器和映射之间使用了 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()有状态操作需要处理整个输入流才能产生结果,所以这里不能部署融合技术,所以所有的过滤都先发生,然后将映射和打印操作融合在一起,排序后?如果我的任何假设不正确,请纠正我,并随时详细说明我已经说过的话。

此外,它如何在幕后决定是否可以将元素融合到一个 channel 中,例如,当 distinct() 操作存在时,是否有一个简单的标志来关闭以阻止它发生就像不存在 distinct() 时一样?

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

最佳答案

无状态 操作(map、filter、flatMap、peek 等)完全融合;我们构建了一个级联的 Consumer 对象链,并将数据倒入其中。每个元素都可以独立于彼此进行操作,因此链中永远不会有任何“卡住”。 (这就是 Louis 所说的如何实现融合的意思——我们将各个阶段组合成一个大函数,并将数据提供给它。)

有状态 操作(distinct、sorted、limit 等)更复杂,并且其行为变化更大。每个有状态操作都可以选择它自己的实现方式,因此它可以选择尽可能少的侵入性方法。例如,distinct(在某些情况下)让元素在经过审查时出来,而 sorted 是一个完整的障碍。 (不同之处在于懒惰的可能性有多大,以及它们如何处理诸如无限源之类的下游限制操作。)

的确,有状态操作通常会破坏融合的一些好处,但不是全部(上游和下游的操作仍然可以融合。)

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

关于Java流操作融合和有状态中间操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35069055/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com