在java 8流中心,中间操作(如 filter
, map
和 peek
(的描述为
...此流的元素...
但是,诸如filter
之类的流中间操作似乎一次处理并返回单个"元素"。例如,Java 8流操作执行订单问题(请参阅输出(和答案。
filter
的API描述是
返回由与给定谓词相匹配的该流元素的流。
但是,Java 8流操作执行订单中提到的代码似乎一次处理并返回单个元素。请阐明API提到的"元素"与代码的单个"元素"的明显处理之间的断开连接。
谢谢。
是的,无状态的中间操作,例如filter
,map
等流管线中随后的中间操作。调用映射功能后,后者将始终将元素发送到后续操作。
例如:
...
.filter(n -> n % 2 == 0) // retain even numbers
.map(n -> n * n) // square it
...
一次一个元素将通过filter
操作,如果当前元素符合所提供的谓词,则将其传递给map
操作。
我认为您理解这部分,而是您的困惑是为什么在Java Doc中写下了:
返回由匹配该流的元素组成的流 给定的谓词。
"返回流",因为每个中间操作都返回新流。
"由元素组成",因为流表示一系列元素,在大多数情况下,有多个元素通过给定的中间操作。
这听起来像是流的元素,但根本不是这种情况。相反,它们可能存储在某些基础集合中或按需生成。
值得注意的是,并非每个中间操作都会一次通过一个元素到下一阶段。例如,sorted
中间操作缓冲所有元素,直到看到输入的末尾,然后将数据发送到后续阶段。
作为阅读,布莱恩·戈兹(Brian Goetz(发表了一篇关于引擎盖下的溪流的精彩帖子。这确实介绍了有关流的详细信息,并且有一个很好的动画由Tagir Valeev提供,展示了如何可视化流。
我认为这里有一些误解,因为过滤器总是返回流。
请参阅与以下相同的签名:
Stream<T> filter(Predicate<? super T> predicate);
因此,任何此类中间操作都会一次返回流,而不是一个元素,您可以执行所有操作,因为您可以在流上执行。
规格也是如此:
返回由匹配该流的元素组成的流 给定的谓词。
map
和filter
中间操作确实在流的每个元素上都执行,但是它们自己返回流。
因此,当我们从上部问题中查看代码时,每个数字1-8将执行过滤器操作,但是它将返回一个新的流,该流仅观察到偶数{2,4,6,,8}。
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());
没有断开连接,因为像流8流API所说的那样,中间运算符(例如filter(Function<?, Boolean> filteringFunction)
(返回流。他们通过在式流中的每个元素上执行给定的filteringFunction
并返回一个新的外流来执行此操作,该流程仅观察已过滤为true
的元素。