gpt4 book ai didi

java - stream 的管道如何在 java 中像 IntPipeline 一样工作

转载 作者:行者123 更新时间:2023-11-30 06:12:22 25 4
gpt4 key购买 nike

我正在学习 Java 8 流,我遇到了一些问题。

假设这段代码:

 new Random().ints().forEach(System.out::println);

在某些时候,它会在内部调用 IntPipeline,我认为它负责生成那些无限期的整数。通过查看 java 源代码很难理解 Streams 实现。

关于流是如何生成的以及管道上的操作是如何连接的,你能给出一个简短的解释或一些好的/易于理解的 Material 吗?上面代码中的例子是随机生成的,这个连接是如何建立的?

最佳答案

Stream 实现分为 Spliterator(特定于输入的代码)和管道(独立于输入的代码)。 Spliterator类似于Iterator。主要区别如下:

  • 它可以将自己拆分为两部分(trySplit 方法)。对于有序拆分器,部分是前缀和后缀(例如,对于数组,它可能是前半部分和后半部分)。对于无序源(如随机数),这两个部分只能生成一些元素。生成的部分能够进一步 split (除非它们变得太小)。此功能对于并行流处理至关重要。

  • 它可以报告其准确或估计的大小。确切的大小可用于为某些流操作预分配内存,如 toArray() 或者只是将其返回给调用者(如 Java-9 中的 count())。估计的大小用于并行流处理以决定何时停止拆分。

  • 它可以报告一些特征,如 ORDERED、SORTED、DISTINCT 等。

  • 它实现了内部迭代:您只有一个方法 tryAdvance 而不是 hasNextnext 这两个方法,它执行提供的 Consumer 一次,除非没有更多元素剩余。

还有 Spliterator 接口(interface)(Spliterator.OfInt 等)的原始特化,可以帮助您处理原始值,如 intlongdouble 高效。

因此,要创建您自己的 Stream 数据源,您必须实现 Spliterator,然后调用 StreamSupport.stream(mySpliterator, isParallel)为原始特化创建 StreamStreamSupport.int/long/doubleStream。所以实际上 Random.ints 调用 StreamSupport.intStream 提供它自己的分离器。您不必自己实现所有 Stream 操作。一般来说,Stream 接口(interface)在 JDK 中针对不同的源只为每个流类型实现一次。有基本的抽象类 AbstractPipeline 和四个实现(ReferencePipeline 用于 StreamIntPipeline 用于 IntStreamLongPipeline 用于 LongStreamDoublePipeline 用于 DoubleStream)。但是您有更多的来源(Collection.stream()Arrays.stream()IntStream.rangeString.chars ()BufferedReader.lines()Files.lines()Random.ints()等,甚至更多出现在 Java-9 中)。所有这些来源都是使用自定义拆分器实现的。实现 Spliterator 比实现整个流管道要简单得多(特别是考虑到并行处理),所以这样的分离是有道理的。

如果你想创建自己的流源,你可以开始扩展AbstractSpliterator .在这种情况下,您只需实现 tryAdvance 并调用提供估计大小和一些特征的父类(super class)构造函数。 AbstractSpliterator 通过将源代码的一部分读入数组(调用已实现的 tryAdvance 方法)并为此前缀创建基于数组的拆分器来提供默认拆分行为。当然,这种策略的性能不是很好,而且通常只能提供有限的并行性,但作为起点它还可以。稍后您可以自己实现 trySplit 以提供更好的拆分策略。

关于java - stream 的管道如何在 java 中像 IntPipeline 一样工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32936082/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com