有人可以告诉我Stream
的中间操作和终端操作有什么区别?
Stream
操作被合并到流程中以处理流。所有操作都是中间或终端..意思?。
答案 0 :(得分:17)
Stream支持多项操作,这些操作分为intermediate
和terminal
操作。
此操作之间的区别在于中间操作是惰性的而终端操作不是。在流上调用中间操作时,不会立即执行操作。仅在该流上调用终端操作时才执行它。在某种程度上,中间操作被存储并且一旦调用终端操作就被调用。您可以链接多个中间操作,在调用终端操作之前,它们都不会执行任何操作。那时,您之前调用的所有中间操作都将与终端操作一起调用。
所有中间操作都返回Stream(可以链接),而终端操作则不返回。中级操作是:
filter(Predicate<T>)
map(Function<T>)
flatmap(Function<T>)
sorted(Comparator<T>)
peek(Consumer<T>)
distinct()
limit(long n)
skip(long n)
终端操作产生非流(无法链接)结果,例如原始值,集合或根本没有值。
终端操作是:
forEach
forEachOrdered
toArray
reduce
collect
min
max
count
anyMatch
allMatch
noneMatch
findFirst
findAny
最后5个是短路终端操作。
答案 1 :(得分:2)
终端意味着结束流程,例如将流收集到列表或聚合值流。
在转换到终端操作的过程中转换到新状态的中级
答案 2 :(得分:2)
您可能已经注意到,在定义流时,方法不仅在整个流上逐个调用,而是在流中的每个元素上执行某些操作。为了能够并行运行这些流,对于每个元素,基本上都有一个完整的流水线。
为了创建多个管道,Java 8+使用builder pattern。在每个中间步骤中,您都可以将过滤器或转换器添加到堆栈中。为了告诉Java从该堆过滤器生成管道,您可以使用终止步骤。最后一步结合了所有不同的管道。通常它只是以定义的格式返回值,例如一个列表,但它也可以为每个元素运行一次函数,或者将结果减少为布尔值或数字。
答案 3 :(得分:2)
根据javadoc:
filter(Predicate)
count()
或forEach(Consumer)
请注意,所有中间操作将不执行,而无需最后进行终端操作。因此模式将是:
stream()
.intemediateOperation1()
.intemediateOperation2()
...
.intemediateOperationN()
.terminalOperation();
答案 4 :(得分:0)
为直观起见,请使用以下代码:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
int sum = numbers.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * n)
.reduce(0, Integer::sum);
filter
和map
是中间操作,reduce
是终止操作。
numbers.stream()
)创建流,因此我们具有:
| 1,2,3,4 | numbers.stream().filter(n -> n % 2 == 0)
):
| 1,2,3,4 | ----- |过滤器| numbers.stream().filter(n -> n % 2 == 0).map(n -> n * n)
):
| 1,2,3,4 | ----- |过滤器| ----- | map | reduce
,这是终端操作,整个流程运行:
| 1,2,3,4 | -> 4 3 2 1-> |过滤器| -> 4 2-> | map | -> 16 4-> |减少| -> 20 请注意,在调用终端操作之前,没有数据流通过该流。
答案 5 :(得分:-1)
Java 8中的中间操作
中间操作会将一个流转换为另一个流,它们由流执行的流水线组成,并且只有在调用某些终端操作后才能执行。中级操作是懒惰的,因此直到需要实际处理时才执行它们。每个中间操作都将返回新的Stream,并且在执行管道的终端操作之前,不会开始遍历每个Stream。
让我们看看中间操作是多么懒惰吗?
我们有一个map()函数,在其中打印当前的学生姓名。仅当我们将终端操作符应用于这些名称时,才会打印这些名称。在下面的示例中,我们应用了collect(terminal operator),并且map()在线程进入运行状态后输出学生姓名。中间操作就是这样工作的。中间操作会将一个流转换为另一个流,它们由流执行的流水线组成,并且只有在调用某些终端操作后才能执行
private static void lazyIntermediateOperations(List<Student> students) throws InterruptedException {
System.out.println("######## Executing lazyIntermediateOperations() : ######## ");
Stream<String> studentStream = students.stream()
.map(student -> {
System.out.printf("In Map : %s\n", student.getName());
return student.getName().toUpperCase();
});
System.out.println("After map statement");
Thread.sleep(5000);
System.out.println("Thread is in Running state now");
studentStream.collect(Collectors.toList());
System.out.println("######## Ending the execution of lazyIntermediateOperations() ######## ");
}
输出
##执行lazyIntermediateOperations():########地图声明后 线程现在处于运行状态 在地图上:索拉卜 在地图上:罗伯特 在地图上:约翰 在地图上:罗马 在地图上:兰迪
##结束lazyIntermediateOperations()的执行Java 8中可用的中间操作:
filter(Predicate<T>)
map(Function<T>)
flatmap(Function<T>)
sorted(Comparator<T>)
peek(Consumer<T>)
distinct()
limit(long n)
skip(long n)
Java 8中的终端操作 终端操作会产生非流(无法链接)结果,例如原始值,集合或根本没有值。 Java 8中可用的终端操作:
forEach
toArray
reduce
collect
min
max
count
Java 8中提供的短路端子操作:
anyMatch
allMatch
noneMatch
findFirst
findAny
有关更多信息,请参阅: https://onlyfullstack.blogspot.com/p/java-8-features.html
https://onlyfullstack.blogspot.com/2018/12/intermediate-and-terminal-operations-in-java-8.html