您能解释以下代码的执行过程吗?主要是sorted
方法。
Stream.of("d2", "a2", "b1", "b3", "c")
.sorted((s1, s2) -> {
System.out.printf("sort: %s; %s\n", s1, s2);
return s1.compareTo(s2);
})
.filter(s -> {
System.out.println("filter: " + s);
return s.startsWith("a");
})
.map(s -> {
System.out.println("map: " + s);
return s.toUpperCase();
})
.forEach(s -> System.out.println("forEach: " + s));
输出:
sort: a2; d2
sort: b1; a2
sort: b1; d2
sort: b1; a2
sort: b3; b1
sort: b3; d2
sort: c; b3
sort: c; d2
filter: a2
map: a2
forEach: A2
filter: b1
filter: b3
filter: c
filter: d2
谢谢,编号:https://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/
答案 0 :(得分:1)
因此Java8
试图通过对任何给定的输入尽快执行所有高阶函数来加快执行速度。也就是说,例如,如果您在列表上连续两次调用map
,则它将仅访问列表的每个元素一次。这样可以加快速度,因为它从2次遍历到了1个。为了说明这一点,请举一个简单的例子:
Stream.of(1, 2, 3)
.map(s -> {
System.out.println("map: " + s.toString());
return s;
})
.map(s -> {
System.out.println("map: " + s.toString());
return s;
})
这将打印:
1
1
2
2
3
3
因为一次“触摸”列表中的每个元素比对两个map
进行完全遍历列表的速度更快!
就您的示例而言,让我们对其进行逐步介绍:
sort: a2; d2
sort: b1; a2
sort: b1; d2
sort: b1; a2
sort: b3; b1
sort: b3; d2
sort: c; b3
sort: c; d2
所有排序需要同时发生,并且所有这些都必须首先发生。这是因为在排序完成之前,计算机无法知道哪个元素将位于哪个位置(即,它无法在同一列表位置上进行两次映射,因为排序可能会改变该位置)
接下来,您基本上是这样的:
Stream.of("a2", "b1", "b3", "c", "d2")
.filter(s -> {
System.out.println("filter: " + s);
return s.startsWith("a");
})
.map(s -> {
System.out.println("map: " + s);
return s.toUpperCase();
})
.forEach(s -> System.out.println("forEach: " + s));
现在,为了最小化列表中的传递,Java将遍历列表中的每个元素并执行filter
,然后执行map
,然后执行forEach
。这是因为这些都不依赖于元素的位置。换句话说,Java看到它可以对每个元素执行所有这些操作,而不是对每个函数重复遍历整个列表三遍!
现在:
filter: a2
map: a2
forEach: A2
我们filter
第一个元素,然后map
在它上面,然后进行最后的forEach
打印。
filter: b1
filter: b3
filter: c
filter: d2
所有这些都将被过滤掉,因此其余函数不会被调用!
答案 1 :(得分:0)
您似乎对为什么输出中连续有几个排序的调用感到困惑。
让我们解释一下;首先,将中间操作分为filter
,map
等的 stateless 和 stateful 等。 sorted
,distinct
等
如Brian Goetz here under Executing a stream pipeline所述:
无状态操作是可以对元素执行的操作 没有任何其他要素的知识。例如,一个 过滤操作只需要检查当前元素即可 确定是包括还是消除它,但是排序操作 必须先查看所有元素,然后才能知道首先发出哪个元素。
强调我的。
排序操作必须先查看所有元素,然后才能将给定元素发射给下一个操作,这就是为什么在输出中连续看到多个排序调用的原因。
此外,您可能还想阅读are Java streams stages sequential?
它在某种程度上衍生自sorted
操作。