【问题标题】:What is the difference between intermediate and terminal operations?中间操作和终端操作有什么区别?
【发布时间】:2018-05-21 04:02:20
【问题描述】:

谁能告诉我Stream 的中间操作和终端操作有什么区别?

Stream 操作组合成管道来处理流。所有的操作要么是中间的,要么是终端的..means?.

【问题讨论】:

  • 流是惰性的,当调用 sum 、 toarray 等终端操作时,代码实际上会做一些事情,而 filter 、 map 是中间的,可能是一个骗子

标签: java java-8 java-stream


【解决方案1】:

一个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个是短路终端操作。

【讨论】:

    【解决方案2】:

    根据javadoc

    • 中间操作会将一个流转换为另一个流,例如map(MapperFn)filter(Predicate)
    • 终端操作会产生结果或副作用,如count()forEach(Consumer)

    请注意,所有中间操作将不会在没有终端操作的情况下执行。所以模式将是:

    stream()
        .intemediateOperation1()
        .intemediateOperation2()
        ...
        .intemediateOperationN()
        .terminalOperation();
    

    【讨论】:

      【解决方案3】:

      终端的意思是结束过程,比如收集一个流到一个列表,或者聚合一个值流。

      过渡到新状态的中间,在通往终端操作的路上

      【讨论】:

      • 它是否缓存任何数据?
      • 不,他们没有。你在哪里看到他们这样做?
      【解决方案4】:

      您可能注意到,当您定义一个流时,这些方法不仅在整个流上被一个一个地调用,而是它们对流中的每个元素执行一些操作。为了能够并行运行这些流,对于每个元素,基本上都有一个完整的管道。

      为了创建多个管道,Java 8+ 使用builder pattern。在每个中间步骤中,您都会将过滤器或转换器添加到堆栈中。为了告诉 Java 从过滤器堆栈生成管道,您使用终止步骤。最后一步结合了所有不同的管道。通常它只是以定义的格式返回值,例如一个列表,但它也可以为每个元素运行一次函数,或者将结果简化为布尔值或数字。

      【讨论】:

        【解决方案5】:

        为了形象化,我们来看看这段代码:

        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. 我们从 List (numbers.stream()) 创建一个流,所以我们有: |1,2,3,4|
        2. 过滤值(numbers.stream().filter(n -&gt; n % 2 == 0)): |1,2,3,4| ----- |过滤器|
        3. 地图(numbers.stream().filter(n -&gt; n % 2 == 0).map(n -&gt; n * n)): |1,2,3,4| ----- |过滤器| ----- |地图|
        4. 最后我们调用reduce,是终端操作,整个流程运行: |1,2,3,4| -> 4 3 2 1 -> |过滤器| -> 4 2 -> |地图| -> 16 4 -> |减少| -> 20

        请注意,在调用终端操作之前,没有数据流过流。

        【讨论】:

          猜你喜欢
          • 2017-11-26
          • 2017-01-04
          • 1970-01-01
          • 1970-01-01
          • 2012-10-30
          • 1970-01-01
          • 2019-08-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多