中间和终端操作有什么区别?

时间:2017-12-07 05:47:34

标签: java java-8

有人可以告诉我Stream的中间操作和终端操作有什么区别?

Stream操作被合并到流程中以处理流。所有操作都是中间或终端..意思?。

6 个答案:

答案 0 :(得分:17)

Stream支持多项操作,这些操作分为intermediateterminal操作。

此操作之间的区别在于中间操作是惰性的而终端操作不是。在流上调用中间操作时,不会立即执行操作。仅在该流上调用终端操作时才执行它。在某种程度上,中间操作被存储并且一旦调用终端操作就被调用。您可以链接多个中间操作,在调用终端操作之前,它们都不会执行任何操作。那时,您之前调用的所有中间操作都将与终端操作一起调用。

所有中间操作都返回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);

filtermap是中间操作,reduce是终止操作。

  1. 我们从列表(numbers.stream())创建流,因此我们具有: | 1,2,3,4 |
  2. 过滤器值(numbers.stream().filter(n -> n % 2 == 0)): | 1,2,3,4 | ----- |过滤器|
  3. 地图(numbers.stream().filter(n -> n % 2 == 0).map(n -> n * n)): | 1,2,3,4 | ----- |过滤器| ----- | map |
  4. 最后我们称为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

Intermediate vs Terminal Operations

有关更多信息,请参阅: https://onlyfullstack.blogspot.com/p/java-8-features.html

https://onlyfullstack.blogspot.com/2018/12/intermediate-and-terminal-operations-in-java-8.html