繁体   English   中英

Java Stream API 惰性求值内部

[英]Java Stream API lazy evaluation internals

我正在写一篇关于 Java Stream API 的文章。 我已经阅读了 Stream 的整个 package 文档,并且在这里查看了类似的问题。

如果我说以下内容:“stream 上的中间操作在终端操作被命中之前不会被评估,这实际上会执行它们,”我是否正确? 我在 StackOverflow 上看到了不同的答案,而且每个中间操作都返回一个 Stream,所以我想知道它是否只是返回自己,然后只是跟踪中间操作以执行它。 这就是“惰性评估/执行”的意思吗?

下面的javadoc老实说给了我混合的信号..也许我只是愚蠢

中间操作返回一个新的 stream。 他们总是很懒惰; 执行诸如 filter() 之类的中间操作实际上并没有执行任何过滤,而是创建了一个新的 stream,当被遍历时,它包含与给定谓词匹配的初始 stream 的元素。 直到管道的终端操作被执行,管道源的遍历才开始。

非常感谢您的时间; 抱歉,如果我遗漏了什么;(我已经坚持了很长时间!

PS: Stream和惰性求值非常相似,但是“每个中间操作都会创建一个新的stream,存储提供的操作/函数并返回新的stream。” 所以基本上,我的问题是,通过新的 stream,它是否意味着与给出的 stream 相同?

所以我想知道它是否刚刚返回

中间操作不会返回给定的 stream。 正如 JavaDoc 所说,它们返回一个新的 stream ,即一个新的 object。

如果是新的 object,它怎么知道之前在 stream 上所做的操作?

……你可能会问。

好吧,对象可以引用其他对象,对吗? 即使您返回执行“映射”的新Stream ,它仍然可以引用“旧流”(又名upstream )。 非常简化的例子:

class StreamThatDoesMapping<U, T> implements Stream<T> {
    private Stream<U> upstream;
    private Function<? super U, ? extends T> mappingFunction;

    public StreamThatDoesMapping(Stream<U> upstream, Function<? super U, ? extends T> mappingFunction) {
        this.upstream = upstream;
        this.mappingFunction = mappingFunction;
    }

    // implementation details...
}

显然,在实现map时,如果您将上游( this )传递给StreamThatDoesMapping ,新的 stream 将“了解”您之前所做的操作! 这就是您可能实现map的方式,再次非常简化:

public <R> Stream<R> map(Function<? super T, ? extends R> mapper) {
    return new StreamThatDoesMapping<>(this, mapper);
}

当您进行终端操作时,您是在“最下游” Stream object 上进行操作,即 object 将从其上游获取元素,因此上游将从上游获取元素, 有点像链表,不是吗?

请注意,这只是下游了解上游的一种方式。 可能还有其他的,但这是ReferencePipeline实现使用的。 这是 JDK 中大多数stream()方法返回的内容。 我强烈建议查看他们的源代码。

如果我说以下内容:“stream 上的中间操作在终端操作被命中之前不会被评估,这实际上会执行它们,”我是否正确?

是的。

我想知道它是否只是自行返回,然后只是跟踪要执行的中间操作。

不。

它返回一个新的Stream object,它是根据之前的Stream ZA8CFDE633119446B8 定义的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM