如何在Java 8中实现延迟流?

Lea*_*ner 19 java-8 java-stream

我正在阅读Java 8,特别是"Streams API".我想知道流是如何懒惰的?

我相信流只是作为一个库添加,并且没有对语言进行任何更改来支持懒惰.另外,如果有人告诉我这是通过反思实现的,我会感到震惊.

Ale*_* C. 23

为什么你需要反思才能得到懒惰?例如,考虑这个类:

class LazySeq<T> {

    private final List<T> list;
    private Predicate<? super T> predicate;

    public LazySeq(List<T> input) {
        this.list = new ArrayList<>(input);
    }

    //Here you just store the predicate, but you don't perform a filtering
    //You could also return a new LazySeq with a new state
    public LazySeq<T> filter(Predicate<? super T> predicate) {
        this.predicate = predicate;
        return this;
    }

    public void forEach(Consumer<? super T> consumer){
        if(predicate == null) {
            list.forEach(consumer);
        } else {
            for(T elem : list) {
                if(predicate.test(elem)) {
                    consumer.accept(elem);
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当您调用filterlazy seq时,过滤不会立即发生,例如:

LazySeq<Integer> lazySeq = new LazySeq<>(Arrays.asList(1, 2, 3, 4));
lazySeq = lazySeq.filter(i -> i%2 == 0);
Run Code Online (Sandbox Code Playgroud)

如果在调用filter后看到序列的内容,你会发现它始终是1, 2, 3, 4.但是,当调用终端操作时,例如forEach,过滤将在使用消费者之前完成.例如:

lazySeq.filter(i -> i%2 == 0).forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

将打印2和4.

这与Streams的原理相同.从源中,链接具有某些属性的操作.这些操作要么是中间的,要么返回惰性流(例如filtermap),要么返回终端(例如forEach).其中一些终端操作是短路的(例如findFirst),因此您可能无法遍历所有管道(例如,您可以考虑在for循环中返回数组索引的早期返回).

当调用终端操作时,这一系列操作开始执行,以便最后得到预期的结果.

当应用中间操作时,可以通过在管道上存储新状态来实现惰性,当您调用终端操作时,您可以逐个访问数据上的所有状态.

Stream API并没有真正实现(它有点复杂),但实际上原理就在这里.


Sle*_*idi 6

没有反思或代理.反思和代理带来了应该避免的性能成本,除非没有替代方案且性能是第一位的Java.

使懒惰成为可能的是做事的功能风格.基本上是以stream源(ex:List),中间操作数(例如:filters,map ..)和终端操作(例如:count,sum等)开始.中间步骤执行延迟,因为您传递了在管道中链接的函数(lambdas),以便在终端步骤执行.

ex: filter(Predicate<? super T>)
Run Code Online (Sandbox Code Playgroud)

filter 在此示例中,需要一个函数来告诉我们流中的对象是否满足某些条件.

Java 7中提供了许多功能,可以提高效率.例如:调用动态来执行lambdas而不是代理或匿名内部类和ForkJoin池来执行并行执行.

如果你对Java 8内部感兴趣,那么你必须看看Brian Goetz领域的专家给出的这个演讲,它在Youtube上.