public static void main(String[] args) throws IOException {
List<String> lst = new ArrayList<>();
lst.add("Alpha");
lst.add("Beta");
lst.add("Gamma");
String joinResult = lst.stream().peek(x->System.out.println(x)).map(x -> {
System.out.println("In the middle");return x+"3";}).peek(System.out::println).collect(Collectors.joining());
System.out.println(joinResult);
}
Run Code Online (Sandbox Code Playgroud)
最后我没有使用collect(Collectors.joining()),而是使用了count()。但是没有打印任何内容。count()没有终端操作吗?count返回的是long,所以应该是这样。真的很奇怪。
上面的代码从头到尾打印每个元素。Alpha -> 中间 ->Alpha3 Beta -> 中间 -> Beta3 依此类推
这就是流的工作原理吗?每个元素都从头到尾进行处理?
您的流源 ( an ArrayList) 具有已知的大小,中间操作 (map()和peek()) 不会影响该大小,因此count()可以在不调用中间操作的情况下确定结果。
文档中明确提到了这一点Stream.count():
API注意事项:
如果实现能够直接从流源计算计数,则它可以选择不执行流管道(顺序或并行)。在这种情况下,不会遍历任何源元素,也不会评估任何中间操作。具有副作用的行为参数可能会受到影响,除非调试等无害情况,否则强烈建议不要这样做。例如,考虑以下流:
Run Code Online (Sandbox Code Playgroud)List<String> l = Arrays.asList("A", "B", "C", "D"); long count = l.stream().peek(System.out::println).count();流源 a 覆盖的元素数量
List是已知的,中间操作 peek 不会注入流或从流中删除元素(可能是 flatMap 或过滤器操作的情况)。因此,计数就是 的大小,List并且不需要执行管道,并且作为副作用,打印出列表元素。
如果您想确保执行中间操作,您可以添加一个虚拟过滤器操作:
long result = lst.stream()
.peek(System.out::println)
.map(x -> { System.out.println("In the middle"); return x+"3"; })
.peek(System.out::println)
.filter(x -> true)
.count();
System.out.println(result);
Run Code Online (Sandbox Code Playgroud)
流是如何处理的?
它是触发流处理的终端操作。
操作向collect()前面的步骤 ( peek()) 请求元素。该peek()步骤依次向其前一个步骤 ( map()) 请求一个元素。该map()步骤向其前一个步骤(第一个peek())询问元素。第一步peek()向源(List)请求一个元素。然后,该元素通过各个步骤传回,直到到达操作collect()。重复此操作,直到源无法提供附加元素为止。
操作count()有点不同。在构建流管道时,每个步骤都会将一些有关自身的信息传递到下一步。在这种情况下,重要的属性Spliterator.SIZED意味着流具有有限的大小,在没有结构源修改的情况下,表示完整遍历将遇到的元素数量的精确计数。该count()操作检查前面的步骤,如果前面的步骤表示具有该特征的流,则它只询问其大小。
中间操作如map()和peek()不会改变通过它们的元素数量,因此将Spliterator.SIZED属性传递到下一个阶段。
中间操作(例如flatMap()和 )filter()可能会将不同数量的元素传递到下一个阶段,因此Spliterator.SIZED从构造的流中删除该属性。
| 归档时间: |
|
| 查看次数: |
77 次 |
| 最近记录: |