当前位置: 首页 > 知识库问答 >
问题:

stream.parallel()不更新spliterator的特性吗?

欧阳英彦
2023-03-14

这个问题是基于这个问题的答案,stream.of和intstream.range之间的区别是什么?

IntStream.range(0, 4)
         .peek(e -> System.out.println(e))
         .sorted()
         .findFirst();
System.out.println(
    IntStream.range(0, 4)
             .spliterator()
             .hasCharacteristics(Spliterator.SORTED)
);
IntStream.range(0, 4)
         .parallel()
         .peek(e -> System.out.println(e))
         .sorted()
         .findFirst();

这将按任何顺序生成如下内容:

2
0
1
3

因此,我希望sorted属性已经被删除,原因是parallel()。但是,下面的代码也返回true

System.out.println(
    IntStream.range(0, 4)
             .parallel()
             .spliterator()
             .hasCharacteristics(Spliterator.SORTED)
);

为什么parallel()不更改sorted属性,并且由于打印了所有四个数字,那么即使sorted属性仍然存在,Java又如何知道流没有排序呢?

共有1个答案

何睿范
2023-03-14

具体如何做到这一点是一个非常具体的实现细节。您必须深入挖掘源代码才能真正了解原因。基本上,并行和顺序管道的处理方式不同。看看abstractPipeline.evaluate,它检查isParallel(),然后根据管道是否并行执行不同的操作。

    return isParallel()
           ? terminalOp.evaluateParallel(this, sourceSpliterator(terminalOp.getOpFlags()))
           : terminalOp.evaluateSequential(this, sourceSpliterator(terminalOp.getOpFlags()));

然后查看sortedops.ofint,您将看到它重写了两个方法

@Override
public Sink<Integer> opWrapSink(int flags, Sink sink) {
    Objects.requireNonNull(sink);

    if (StreamOpFlag.SORTED.isKnown(flags))
        return sink;
    else if (StreamOpFlag.SIZED.isKnown(flags))
        return new SizedIntSortingSink(sink);
    else
        return new IntSortingSink(sink);
}

@Override
public <P_IN> Node<Integer> opEvaluateParallel(PipelineHelper<Integer> helper,
                                               Spliterator<P_IN> spliterator,
                                               IntFunction<Integer[]> generator) {
    if (StreamOpFlag.SORTED.isKnown(helper.getStreamAndOpFlags())) {
        return helper.evaluate(spliterator, false, generator);
    }
    else {
        Node.OfInt n = (Node.OfInt) helper.evaluate(spliterator, true, generator);

        int[] content = n.asPrimitiveArray();
        Arrays.parallelSort(content);

        return Nodes.node(content);
    }
}

如果opwrapsink是一个顺序管道,则最终将调用它;如果它是一个并行流,则将调用opevaluateParallel(顾名思义)。请注意,如果管道已经排序,opwrapsink不会对给定的接收器执行任何操作(只是不加更改地返回它),但opevaluateParallex总是计算拆分器。

还要注意,并行性和排序性并不是相互排斥的。您可以拥有一个具有这些特性的任意组合的流。

“排序”是拆分器的一个特征。从技术上讲,它不是的特征(就像“Parallel”一样)。当然,parallex可以创建一个具有全新特性的全新分裂器(从原始分裂器获取元素)的流,但为什么要这样做呢?Id想象一下,在任何情况下,您都必须以不同的方式处理并行流和顺序流。

 类似资料:
  • 为了试图深入理解Java流和spliterator,我有一些关于spliterator特性的微妙问题: Q1:与(不带参数的stream.of()) :已沉降,大小 :沉降的、不可变的、有大小的、有序的 为什么不具有相同的特性?请注意,当它与stream.concat()结合使用时(特别是没有)会产生影响。我想说不仅应该具有不可变和有序性,而且还应该具有DISTINCT和nonnull。只有一个参

  • 哪些流操作使用、和拆分器特性?它们在这些操作中如何发挥作用? 我不是问这些标志是什么,这在文档中很容易找到。我在问哪些操作使用它们以及如何使用它们。

  • 本文向大家介绍HTML5的新特性相关面试题,主要包含被问及HTML5的新特性时的应答技巧和注意事项,需要的朋友参考一下 (1) 绘画canvas (2) 用于媒介回放的video和audio元素 (3) 本地离线存储localStorage长期存储数据,浏览器关闭后数据不丢失 (4) sessionStorage的数据在浏览器关闭后自动删除 (5) 语义化更好的内容元素,比如article,foo

  • 1. ENUM枚举 1.1 枚举概述 枚举是指将变量的值一一列出来,变量的值只限于列举出来的值的范围内。举例:一周只有7天,一年只有12个月等。 回想单例设计模式:单例类是一个类只有一个实例 那么多例类就是一个类有多个实例,但不是无限个数的实例,而是有限个数的实例。这才能是枚举类。 格式是:只有枚举项的枚举类 public enum 枚举类名 { 枚举项1,枚举项2,枚举项3…;

  • 我正在尝试更新当前登录用户的密码。但它显示了零点异常。 配置文件控制器: ProfileService: 给我这个错误: 2019-07-09 01:55:04.284错误---[nio-8080-exec-8]o.g.web.errors.GrailsExceptionResolver: NullPointerExcture发生时处理请求:[POST] /profile/doPasswordCh

  • 这个页面描述了新添加到 AutoHotkey_L 分支的功能,现在简称为“AutoHotkey 1.1”。 流程控制   Break LoopLabel 退出一个循环或任意数目的嵌套循环. Continue LoopLabel 继续循环, 即使在任意数目的嵌套循环中. For x,y in z 从头到为尾循环对象的内容. Loop Until 循环直到条件为真. 可用于任意类型的循环. Try..