java - Java Stream API 是如何选择执行计划的?

标签 java java-stream

我刚开始学习 Java 8 中的 Stream API 和一般的函数式编程,但对 Java 并不陌生。我有兴趣了解和了解 Stream API 如何选择执行计划。

它如何知道哪些部分需要并行化,哪些部分不需要?存在多少种执行计划?

基本上,我想知道为什么 Java 8 中的 Streams 有助于使事情变得更快,以及它如何发挥这种“魔力”。

我找不到太多关于这一切如何运作的文献。

最佳答案

这个问题有点宽泛,不好详细解释,但我会尽力回答到满意的程度。我还使用了 ArrayList 的 Stream 示例。

当我们创建流时,返回的对象称为 ReferencePipeline .这个对象可以说是“默认流”对象,因为它还没有任何功能。现在我们必须在惰性方法和急切方法之间做出选择。因此,让我们分别看一个示例。

示例一:filter(Predicate<?>)方法:

filter()方法声明如下:

@Override
public final Stream<P_OUT> filter(Predicate<? super P_OUT> predicate) {
    Objects.requireNonNull(predicate);
    return new StatelessOp<P_OUT, P_OUT>(this, StreamShape.REFERENCE,
                                 StreamOpFlag.NOT_SIZED) {
        @Override
        Sink<P_OUT> opWrapSink(int flags, Sink<P_OUT> sink) {
            return new Sink.ChainedReference<P_OUT, P_OUT>(sink) {
                @Override
                public void begin(long size) {
                    downstream.begin(-1);
                }

                @Override
                public void accept(P_OUT u) {
                    if (predicate.test(u))
                        downstream.accept(u);
                }
            };
        }
    };
}

如您所见,它返回一个 StatelessOp 对象,它基本上是一个新的 ReferencePipeline,其中过滤器评估现在“启用”。换句话说:每次我们向流中添加新的“功能”时,它都会基于旧的流水线创建一个新的流水线,并使用适当的操作标志/方法覆盖。
正如您可能已经知道的那样,在调用急切操作之前不会评估流。所以我们需要一个急切的方法来评估流。

示例二:forEach(Consumer<?>)方法:

@Override
public void forEach(Consumer<? super P_OUT> action) {
    evaluate(ForEachOps.makeRef(action, false));
}

一开始这很短,evaluate()方法只是调用 invoke()方法。在这里了解什么很重要 ForEachOps.makeRef()做。它设置了必要的最后标志并创建了一个 ForEachTask<>这与 ForkJoinTask 完全一样目的。又开心Andrew找到一个不错的paper关于它们的工作原理。


注意:可以找到确切的源代码here .

关于java - Java Stream API 是如何选择执行计划的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49897078/

相关文章:

java - Spring Data Elastic Search - 按距离对地理位置进行排序

Java - 给定条件合并列表对象

java-8 - java 8 并行流与 ForkJoinPool 和 ThreadLocal

java - Stream 内的 Bigdecimal 求和

java-8 - 使用 Java 8 将复杂对象列表转换为 Map

java - 根据内部日期列表对 JAVA 父列表进行排序

java - 为什么在将字符串转换为 int 数组时得到空指针?

java - 使用 Java 和 JMX/MBean 访问 Weblogic JMS

java - 关于在调用查询之前使用 JPA 刷新的问题

java - 使用 Class<?> 变量实例化参数化类型类