List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
List<Integer> twoEvenSquares = numbers.stream().filter(n -> {
System.out.println("filtering " + n);
return n % 2 == 0;
}).map(n -> {
System.out.println("mapping " + n);
return n * n;
}).limit(2).collect(Collectors.toList());
for(Integer i : twoEvenSquares)
{
System.out.println(i);
}
执行时,下面的逻辑输出出现
filtering 1
filtering 2
mapping 2
filtering 3
filtering 4
mapping 4
4
16
如果流遵循短路概念(我们使用限制流操作),那么输出必须如下所示:
filtering 1
filtering 2
filtering 3
filtering 4
mapping 2
mapping 4
4
16
因为在过滤2之后,我们还需要再找到一个元素来分层限制(2),操作,所以为什么输出不是像我解释的那样呢?
5条答案
按热度按时间0s7z1bwu1#
这是中间流操作的延迟执行/评估的结果。
操作链是按照从
collect()
至filter()
,值在上一步生成后立即被每个步骤消耗。为了更清楚地描述发生了什么:
唯一的终端操作
collect()
开始评估链。limit()
开始评估其祖先map()
开始评估其祖先filter()
开始使用源流中的值1
进行评估,2
计算并生成第一个值map()
使用其祖先返回的第一个值并生成一个值limit()
消耗这个价值collect()
收集第一个值limit()
需要来自map()
来源map()
需要来自其祖先的另一个值filter()
继续评估以产生另一个结果,并在评估之后3
以及4
产生新的价值4
map()
消耗它并产生新的价值limit()
使用新值并返回它collect()
收集最后一个值。从java.util.stream文档:
流操作分为中间操作和终端操作,并结合起来形成流管道。流管道由源(如集合、数组、生成器函数或i/o通道)组成;后跟零个或多个中间操作,如stream.filter或stream.map;以及stream.foreach或stream.reduce等终端操作。
中间操作返回一个新的流。他们总是懒惰;执行诸如filter()之类的中间操作实际上并不执行任何过滤,而是创建一个新的流,在遍历时,该流包含与给定 predicate 匹配的初始流元素。在执行管道的终端操作之前,不会开始遍历管道源。
8iwquhpp2#
这个
Stream
api并不意味着提供有关操作执行顺序的保证。这就是为什么你应该使用无副作用的功能。“短路”并没有改变任何事情,它只是关于不执行超过必要的操作(并且尽可能在有限的时间内完成,甚至对于无限的流源)。当你查看你的输出时,你会发现一切正常。执行的操作与您期望的操作匹配,结果也匹配。只是顺序不匹配,这不是因为概念,而是你对实现的错误假设。但是,如果您考虑一个不使用中间存储的实现必须是什么样子的,您就会得出结论:它必须完全像所观察到的那样。一
Stream
将一个接一个地处理每个项目,在下一个项目之前对其进行过滤、Map和收集。p1tboqfb3#
你注意到的行为是正确的。为了确定某个数字是否通过整个流管道,必须在所有管道步骤中运行该数字。
现在管道可以结束了,因为我们有两个数字通过管道。
arknldoa4#
filter
以及map
是中间操作。如文件所述:中间操作返回一个新的流。他们总是懒惰;执行诸如filter()之类的中间操作实际上并不执行任何过滤,而是创建一个新的流,在遍历时,该流包含与给定 predicate 匹配的初始流元素。在执行管道的终端操作之前,不会开始遍历管道源。
[...]
缓慢地处理流可以显著提高效率;在上面的filter-map-sum示例这样的管道中,过滤、Map和求和可以融合到数据的一次传递中,中间状态最小。
所以当你调用终端操作(即
collect()
),您可以这样想(这是非常简化的(您将使用收集器来累积管道的内容,流是不可编辑的,…)并且不编译,但它只是可视化的东西):bpzcxfmw5#
流是基于拉的。只有终端操作(如
collect
)将导致项目被消耗。从概念上讲,这意味着
collect
将从limit
,limit
从map
以及map
从filter
,和filter
从小溪里。你问题中的代码示意性地导致
这和你第一次打印出来的一致。