Lazy Evaluation和Eager Evaluation如何在Java 8中运行

Tar*_*nti 3 java lazy-evaluation java-8

我理解Streams是懒惰的,直到在流上调用终端方法.我所知道的是,在调用终端方法之后,所有中间方法都按其调用的顺序执行.

但是通过以下程序,我无法理解流是如何工作的.这是代码,我试过了.

import java.util.*;
import java.util.stream.*;

class TestEagerLazy
{
    public static void main(String[] args) {
        ArrayList<Integer> a = new ArrayList<>();

        a.add(4);a.add(5);a.add(8);
        a.add(7);a.add(3);a.add(65);
        a.add(87);a.add(2);a.add(12);
        a.add(58);a.add(42);

        Stream<Integer> st = a.stream().filter(b->{System.out.println("Tested: " + b);return (b%2)==0;});

        Spliterator<Integer> it = st.spliterator();

        System.out.println("\n\nIterator Results:");
        while(it.tryAdvance((j)->System.out.println("iter: "+j)));


        System.out.println("Last Statement");


    }
}
Run Code Online (Sandbox Code Playgroud)

我期望在流的spliterator上假设tryAdvance的输出如下:

Iterator Results:
Tested: 4
Tested: 5
Tested: 8
Tested: 7
Tested: 3
Tested: 65
Tested: 87
Tested: 2
Tested: 12
Tested: 58
Tested: 42
iter: 4
iter: 8
iter: 2
iter: 12
iter: 58
iter: 42
Last Statement
Run Code Online (Sandbox Code Playgroud)

但我得到的输出如下:

Iterator Results:
Tested: 4
iter: 4
Tested: 5
Tested: 8
iter: 8
Tested: 7
Tested: 3
Tested: 65
Tested: 87
Tested: 2
iter: 2
Tested: 12
iter: 12
Tested: 58
iter: 58
Tested: 42
iter: 42
Last Statement
Run Code Online (Sandbox Code Playgroud)

什么是确切的程序流程?程序如何从tryAdvance流向流上并返回.

4ca*_*tle 6

无状态流旨在处理可能无限量的元素.为此,流不能尝试一次评估所有元素上的每个操作.

顺序流总是一次执行一个元素的管道.在下一个元素开始之前,每个元素都会遍历整个管道.这是允许惰性评估有效的原因.它允许流短路,例如用findFirstallMatch.如果在每个阶段一次处理所有元素,则流将无法处理无限数据源,例如来自Stream.iterate.

代码的输出表明元素一次一个地通过管道:

Iterator Results:
Tested: 4   // starting 1st element
iter: 4     // ending 1st element
Tested: 5   // starting 2nd element (fails the filter)
Tested: 8   // starting 3rd element
iter: 8     // ending 3rd element
Tested: 7   // starting 4th element (fails the filter)
...
Last Statement
Run Code Online (Sandbox Code Playgroud)

JavaDoc中更一般地解释了这些行为.

  • @Andreas:我不认为"拖延"是合适的,因为这意味着Stream实现会做其他事情(编写Stackoverflow贡献?)而不是开始工作...... (3认同)
  • 正如[javadoc](https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#package.description)所说:*懒惰寻求.许多流操作(例如过滤,映射或重复删除)可以懒惰地实现,从而暴露出优化的机会.例如,"找到带有三个连续元音的第一个`String`"不需要检查所有输入字符串.*换句话说,`filter()`方法直到需要时才被调用,也就是懒惰.这真的是"懒惰"的定义.*(但也许他们应该称之为"拖延"?)* (2认同)