Module java.base
Package java.util.stream

Interface DoubleStream

所有超接口:
AutoCloseable, BaseStream<Double,DoubleStream>

public interface DoubleStream extends BaseStream<Double,DoubleStream>
支持顺序和并行聚合操作的原始双精度元素序列。这是Streamdouble原始特化版本。

以下示例说明了使用StreamDoubleStream进行聚合操作,计算红色小部件的重量总和:


     double sum = widgets.stream()
                         .filter(w -> w.getColor() == RED)
                         .mapToDouble(w -> w.getWeight())
                         .sum();
 
有关流、流操作、流管道和并行性的其他规范,请参阅Stream的类文档和java.util.stream的包文档。
自Java版本:
1.8
另请参见:
  • Method Details

    • filter

      DoubleStream filter(DoublePredicate predicate)
      返回由此流的元素组成的流,这些元素与给定谓词匹配。

      这是一个中间操作

      参数:
      predicate - 一个非干扰无状态的谓词,应用于每个元素以确定是否应包含
      返回:
      新流
    • map

      返回由将给定函数应用于此流的元素的结果组成的流。

      这是一个中间操作

      参数:
      mapper - 一个非干扰无状态的函数,应用于每个元素
      返回:
      新流
    • mapToObj

      <U> Stream<U> mapToObj(DoubleFunction<? extends U> mapper)
      返回由将给定函数应用于此流的元素的结果组成的对象值Stream

      这是一个中间操作

      类型参数:
      U - 新流的元素类型
      参数:
      mapper - 一个非干扰无状态的函数,应用于每个元素
      返回:
      新流
    • mapToInt

      IntStream mapToInt(DoubleToIntFunction mapper)
      返回由将给定函数应用于此流的元素的结果组成的IntStream

      这是一个中间操作

      参数:
      mapper - 一个非干扰无状态的函数,应用于每个元素
      返回:
      新流
    • mapToLong

      LongStream mapToLong(DoubleToLongFunction mapper)
      返回由将给定函数应用于此流的元素的结果组成的LongStream

      这是一个中间操作

      参数:
      mapper - 一个非干扰无状态的函数,应用于每个元素
      返回:
      新流
    • flatMap

      DoubleStream flatMap(DoubleFunction<? extends DoubleStream> mapper)
      返回由将此流的每个元素替换为应用提供的映射函数产生的映射流的内容组成的结果流。每个映射流在其内容放入此流后关闭。(如果映射流为null,则使用空流。)

      这是一个中间操作

      参数:
      mapper - 一个非干扰无状态的函数,应用于每个元素,产生一个新值的DoubleStream
      返回:
      新流
      参见:
    • mapMulti

      返回一个流,由替换此流的每个元素为多个元素的结果组成,具体为零个或多个元素。替换是通过将提供的映射函数应用于每个元素,并与接受替换元素的consumer参数一起执行的。映射函数零次或多次调用消费者以提供替换元素。

      这是一个中间操作

      如果consumer参数在应用于映射函数的范围之外使用,则结果是未定义的。

      实现要求:
      默认实现在此流上调用flatMap,传递一个行为如下的函数。首先,它使用一个DoubleConsumer调用映射函数,将替换元素累积到新创建的内部缓冲区中。当映射函数返回时,它从内部缓冲区创建一个DoubleStream。最后,它将此流返回给flatMap
      参数:
      mapper - 一个非干扰无状态的函数,生成替换元素
      返回:
      新流
      自 JDK 版本:
      16
      参见:
    • distinct

      DoubleStream distinct()
      返回一个由此流的不同元素组成的流。元素根据Double.compare(double, double)进行比较。

      这是一个有状态的中间操作

      返回:
      结果流
    • sorted

      DoubleStream sorted()
      返回一个按排序顺序排列的由此流的元素组成的流。元素根据Double.compare(double, double)进行比较。

      这是一个有状态的中间操作

      返回:
      结果流
    • peek

      DoubleStream peek(DoubleConsumer action)
      返回一个由此流的元素组成的流,同时在从生成的流中消耗元素时对每个元素执行提供的操作。

      这是一个中间操作

      对于并行流管道,操作可能在上游操作提供的任何时间和任何线程中调用。如果操作修改共享状态,则负责提供所需的同步。

      API 注意:
      此方法主要用于支持调试,您希望看到元素在管道中流过某一点时的情况:
      
           DoubleStream.of(1, 2, 3, 4)
               .filter(e -> e > 2)
               .peek(e -> System.out.println("Filtered value: " + e))
               .map(e -> e * e)
               .peek(e -> System.out.println("Mapped value: " + e))
               .sum();
       

      在流实现能够优化掉一些或所有元素的生成(例如使用findFirst等短路操作,或在count()中描述的示例中),对于这些元素不会调用操作。

      参数:
      action - 一个非干扰操作,对从流中消耗的元素执行操作
      返回:
      新流
    • limit

      DoubleStream limit(long maxSize)
      返回一个由此流的元素组成的流,截断长度不超过maxSize

      这是一个短路有状态的中间操作

      API 注意:
      虽然limit()在顺序流管道上通常是廉价的操作,但在有序并行管道上可能非常昂贵,特别是对于较大的maxSize值,因为limit(n)被限制为返回不仅仅是任何n个元素,而是遵循遇到顺序的n个元素。使用无序流源(例如generate(DoubleSupplier))或通过BaseStream.unordered()去除排序约束可能会显著加快有序并行管道中limit()的速度。如果您的情况允许,如果需要与遇到顺序一致,并且在并行管道中使用limit()时遇到性能或内存利用问题,则切换到使用BaseStream.sequential()进行顺序执行可能会提高性能。
      参数:
      maxSize - 流应限制的元素数量
      返回:
      新流
      抛出:
      IllegalArgumentException - 如果maxSize为负数
    • skip

      DoubleStream skip(long n)
      返回一个由此流的剩余元素组成的流,丢弃流的前n个元素。如果此流包含的元素少于n个,则将返回一个空流。

      这是一个有状态的中间操作

      API 注意:
      虽然skip()在顺序流管道上通常是廉价的操作,但在有序并行管道上可能非常昂贵,特别是对于较大的n值,因为skip(n)被限制为跳过不仅仅是任何n个元素,而是遵循遇到顺序的n个元素。使用无序流源(例如generate(DoubleSupplier))或通过BaseStream.unordered()去除排序约束可能会显著加快有序并行管道中skip()的速度。如果您的情况允许,如果需要与遇到顺序一致,并且在并行管道中使用skip()时遇到性能或内存利用问题,则切换到使用BaseStream.sequential()进行顺序执行可能会提高性能。
      参数:
      n - 要跳过的前导元素数量
      返回:
      新流
      抛出:
      IllegalArgumentException - 如果n为负数
    • takeWhile

      default DoubleStream takeWhile(DoublePredicate predicate)
      返回,如果此流是有序的,则由从此流中获取的元素组成的流,这些元素构成了与给定谓词匹配的最长前缀。否则,如果此流是无序的,则返回由从此流中获取的与给定谓词匹配的元素子集组成的流。

      如果此流是有序的,则最长前缀是此流的元素的连续序列,这些元素与给定谓词匹配。序列的第一个元素是此流的第一个元素,紧随序列最后一个元素的元素不匹配给定谓词。

      如果此流是无序的,并且此流的一些(但不是全部)元素与给定谓词匹配,则此操作的行为是不确定的;它可以获取匹配元素的任何子集(包括空集)。

      无论此流是有序还是无序,如果此流的所有元素都与给定谓词匹配,则此操作获取所有元素(结果与输入相同),或者如果流的没有元素与给定谓词匹配,则不获取任何元素(结果是空流)。

      这是一个短路有状态的中间操作

      API 注意:
      虽然takeWhile()在顺序流管道上通常是廉价的操作,但在有序并行管道上可能非常昂贵,因为该操作被限制为返回不仅仅是任何有效前缀,而是遵循遇到顺序的元素中最长的前缀。使用无序流源(例如generate(DoubleSupplier))或通过BaseStream.unordered()去除排序约束可能会显著加快有序并行管道中takeWhile()的速度。如果您的情况允许,如果需要与遇到顺序一致,并且在并行管道中使用takeWhile()时遇到性能或内存利用问题,则切换到使用BaseStream.sequential()进行顺序执行可能会提高性能。
      实现要求:
      默认实现获取此流的spliterator,包装该spliterator以支持此操作在遍历时的语义,并返回与包装的spliterator关联的新流。返回的流保留此流的执行特性(即根据BaseStream.isParallel()的并行或顺序执行),但包装的spliterator可能选择不支持拆分。当关闭返回的流时,将调用返回流和此流的关闭处理程序。
      参数:
      predicate - 一个非干扰无状态的谓词,应用于元素以确定元素的最长前缀。
      返回:
      新流
      自 JDK 版本:
      9
    • dropWhile

      default DoubleStream dropWhile(DoublePredicate predicate)
      返回,如果此流是有序的,则返回一个流,该流由匹配给定谓词的元素的最长前缀之后剩余的元素组成。否则,如果此流是无序的,则返回一个流,该流由匹配给定谓词的元素的子集之后剩余的元素组成。

      如果此流是有序的,则最长前缀是此流的元素的连续序列,这些元素与给定谓词匹配。序列的第一个元素是此流的第一个元素,紧随序列最后一个元素的元素不匹配给定谓词。

      如果此流是无序的,并且此流的一些(但不是全部)元素与给定谓词匹配,则此操作的行为是不确定的;它可以自由地丢弃匹配元素的任何子集(包括空集)。

      无论此流是有序还是无序,如果此流的所有元素都与给定谓词匹配,则此操作会丢弃所有元素(结果是空流),或者如果流的没有元素与给定谓词匹配,则不会丢弃任何元素(结果与输入相同)。

      这是一个有状态的中间操作

      API 注意:
      虽然dropWhile()在顺序流管道上通常是一项廉价操作,但在有序并行管道上可能会非常昂贵,因为该操作受限于返回不仅是任何有效前缀,而是遵守遇到顺序的元素的最长前缀。使用无序流源(例如generate(DoubleSupplier))或通过BaseStream.unordered()去除排序约束可能会显著加快并行管道中dropWhile()的速度,如果您的情况允许的话。如果需要与遇到顺序一致,并且在并行管道中使用dropWhile()时性能或内存利用率不佳,则切换到使用BaseStream.sequential()进行顺序执行可能会提高性能。
      实现要求:
      默认实现获取此流的spliterator,包装该spliterator以支持此操作在遍历时的语义,并返回与包装的spliterator关联的新流。返回的流保留此流的执行特性(即根据BaseStream.isParallel()的并行或顺序执行),但包装的spliterator可能选择不支持拆分。当关闭返回的流时,将调用返回流和此流的关闭处理程序。
      参数:
      predicate - 一个非干扰无状态的谓词,用于确定元素的最长前缀。
      返回:
      新流
      自 JDK 版本:
      9
    • forEach

      void forEach(DoubleConsumer action)
      对此流的每个元素执行操作。

      这是一个终端操作

      对于并行流管道,此操作不保证遵守流的遇到顺序,因为这样做会牺牲并行性的好处。对于任何给定的元素,操作可以在库选择的任何时间和任何线程中执行。如果操作访问共享状态,则负责提供所需的同步。

      参数:
      action - 一个非干扰操作,对元素执行操作
    • forEachOrdered

      void forEachOrdered(DoubleConsumer action)
      对此流的每个元素执行操作,确保对具有定义的遇到顺序的流中的每个元素按顺序处理。

      这是一个终端操作

      参数:
      action - 一个非干扰操作,对元素执行操作
      参见:
    • toArray

      double[] toArray()
      返回包含此流的元素的数组。

      这是一个终端操作

      返回:
      包含此流的元素的数组
    • reduce

      double reduce(double identity, DoubleBinaryOperator op)
      对此流的元素执行归约操作,使用提供的身份值和一个关联累积函数,并返回归约值。这等效于:
      
           double result = identity;
           for (double element : this stream)
               result = accumulator.applyAsDouble(result, element)
           return result;
       
      但不受限于顺序执行。

      identity值必须是累加器函数的身份。这意味着对于所有xaccumulator.apply(identity, x)等于x。累加器函数必须是一个关联函数。

      这是一个终端操作

      API 注意:
      求和、最小值、最大值和平均值都是归约的特殊情况。对一系列数字求和可以表示为:
      
           double sum = numbers.reduce(0, (a, b) -> a+b);
       
      或更简洁地:
      
           double sum = numbers.reduce(0, Double::sum);
       

      虽然这可能看起来比在循环中简单地改变运行总数更为迂回,但归约操作更加优雅地并行化,无需额外的同步,并且极大减少了数据竞争的风险。

      参数:
      identity - 累加函数的身份值
      op - 一个关联非干扰无状态函数,用于组合两个值
      返回:
      归约的结果
      参见:
    • reduce

      对此流的元素执行归约操作,使用一个关联累积函数,并返回描述归约值的OptionalDouble,如果有的话。这等效于:
      
           boolean foundAny = false;
           double result = null;
           for (double element : this stream) {
               if (!foundAny) {
                   foundAny = true;
                   result = element;
               }
               else
                   result = accumulator.applyAsDouble(result, element);
           }
           return foundAny ? OptionalDouble.of(result) : OptionalDouble.empty();
       
      但不受限于顺序执行。

      累加器函数必须是一个关联函数。

      这是一个终端操作

      参数:
      op - 一个关联非干扰无状态函数,用于组合两个值
      返回:
      归约的结果
      参见:
    • collect

      <R> R collect(Supplier<R> supplier, ObjDoubleConsumer<R> accumulator, BiConsumer<R,R> combiner)
      对此流的元素执行可变归约操作。可变归约是指减少值是一个可变结果容器,例如ArrayList,元素通过更新结果的状态而不是替换结果来合并。这会产生一个等效于:
      
           R result = supplier.get();
           for (double element : this stream)
               accumulator.accept(result, element);
           return result;
       

      reduce(double, DoubleBinaryOperator)一样,collect操作可以并行化,而无需额外的同步。

      这是一个终端操作

      类型参数:
      R - 可变结果容器的类型
      参数:
      supplier - 一个创建新的可变结果容器的函数。对于并行执行,可能会多次调用此函数,并且每次必须返回一个新值。
      accumulator - 一个关联非干扰无状态函数,必须将一个元素折叠到结果容器中。
      combiner - 一个关联非干扰无状态函数,接受两个部分结果容器并合并它们,必须与累加器函数兼容。组合函数必须将第二个结果容器中的元素折叠到第一个结果容器中。
      返回:
      归约的结果
      参见:
    • sum

      double sum()
      返回此流中元素的总和。求和是减少的特殊情况。如果浮点求和是精确的,那么此方法将等同于:
      
           return reduce(0, Double::sum);
       
      但是,由于浮点求和不是精确的,上述代码不一定等同于此方法执行的求和计算。

      浮点求和的值既取决于输入值,也取决于加法操作的顺序。此方法的加法操作顺序故意未定义,以便提高实现的灵活性,以改善计算结果的速度和准确性。特别是,此方法可以使用补偿求和或其他技术来减少数值求和中的误差边界,与对double值进行简单求和相比。由于操作顺序未指定并且可能使用不同的求和方案,因此此方法的输出可能会因相同的输入元素而有所不同。

      各种条件可能导致计算出非有限总和。即使所有被求和的元素都是有限的,也可能发生这种情况。如果任何元素是非有限的,则总和将是非有限的:

      • 如果任何元素是NaN,则最终总和将是NaN。
      • 如果元素包含一个或多个无穷大,则总和将是无穷大或NaN。
        • 如果元素包含相反符号的无穷大,则总和将是NaN。
        • 如果元素包含一种符号的无穷大,并且中间总和溢出为相反符号的无穷大,则总和可能是NaN。
      即使所有元素的中间总和为有限值,也可能溢出为相反符号的无穷大;如果发生这种情况,则最终总和将是NaN,即使所有元素都是有限的。如果所有元素都是零,则不能保证零的符号在最终总和中被保留。

      这是一个终端操作

      API 注意:
      按绝对值递增排序的元素往往会产生更准确的结果。
      返回:
      此流中元素的总和
    • min

      返回描述此流中最小元素的OptionalDouble,如果此流为空,则返回一个空的OptionalDouble。如果任何流元素为NaN,则最小元素将是Double.NaN。与数值比较运算符不同,此方法认为负零严格小于正零。这是减少的特殊情况,等同于:
      
           return reduce(Double::min);
       

      这是一个终端操作

      返回:
      包含此流中最小元素的OptionalDouble,如果流为空则返回一个空的optional
    • max

      返回描述此流中最大元素的OptionalDouble,如果此流为空,则返回一个空的OptionalDouble。如果任何流元素为NaN,则最大元素将是Double.NaN。与数值比较运算符不同,此方法认为负零严格小于正零。这是减少的特殊情况,等同于:
      
           return reduce(Double::max);
       

      这是一个终端操作

      返回:
      包含此流中最大元素的OptionalDouble,如果流为空则返回一个空的optional
    • count

      long count()
      返回此流中元素的计数。这是减少的特殊情况,等同于:
      
           return mapToLong(e -> 1L).sum();
       

      这是一个终端操作

      API 注意:
      如果能够直接从流源计算计数,则实现可能选择不执行流管道(顺序或并行)。在这种情况下,不会遍历任何源元素,也不会评估任何中间操作。强烈不建议具有副作用的行为参数,除了像调试这样的无害情况。例如,考虑以下流:
      
           DoubleStream s = DoubleStream.of(1, 2, 3, 4);
           long count = s.peek(System.out::println).count();
       
      流源涵盖的元素数量是已知的,中间操作peek不会向流注入或移除元素(这可能是flatMapfilter操作的情况)。因此,计数为4,不需要执行流水线,并且作为副作用打印出元素。
      返回:
      此流中元素的计数
    • average

      OptionalDouble average()
      返回描述此流中元素的算术平均值的OptionalDouble,如果此流为空,则返回一个空的optional。

      计算的平均值在数值上可能会有所变化,并且具有与计算总和相同的特殊情况行为;有关详细信息,请参见sum()

      平均值是减少的特殊情况。

      这是一个终端操作

      API 注意:
      按绝对值递增排序的元素往往会产生更准确的结果。
      返回:
      包含此流中平均元素的OptionalDouble,如果流为空则返回一个空的optional
    • summaryStatistics

      DoubleSummaryStatistics summaryStatistics()
      返回描述此流中元素的各种摘要数据的DoubleSummaryStatistics。这是减少的特殊情况。

      这是一个终端操作

      返回:
      描述此流中元素的各种摘要数据的DoubleSummaryStatistics
    • anyMatch

      boolean anyMatch(DoublePredicate predicate)
      返回此流中任何元素是否与提供的谓词匹配。如果不需要确定结果,则可能不会对所有元素评估谓词。如果流为空,则返回false,并且不会评估谓词。

      这是一个短路终端操作

      API 注意:
      此方法评估流元素上的谓词的存在量化(对于某个 x P(x))。
      参数:
      predicate - 一个非干扰无状态的谓词,应用于此流的元素
      返回:
      如果流中的任何元素与提供的谓词匹配,则返回true,否则返回false
    • allMatch

      boolean allMatch(DoublePredicate predicate)
      返回此流中所有元素是否与提供的谓词匹配。如果不需要确定结果,则可能不会对所有元素评估谓词。如果流为空,则返回true,并且不会评估谓词。

      这是一个短路终端操作

      API 注意:
      此方法评估流元素上的谓词的全称量化(对于所有 x P(x))。如果流为空,则量化被认为是虚假满足,并且始终为true(不考虑 P(x))。
      参数:
      predicate - 一个非干扰无状态的谓词,应用于此流的元素
      返回:
      如果流中的所有元素都与提供的谓词匹配,或者流为空,则返回true,否则返回false
    • noneMatch

      boolean noneMatch(DoublePredicate predicate)
      返回此流中没有元素是否与提供的谓词匹配。如果不需要确定结果,则可能不会对所有元素评估谓词。如果流为空,则返回true,并且不会评估谓词。

      这是一个短路终端操作

      API 注意:
      此方法评估流元素上的否定谓词的全称量化(对于所有 x ~P(x))。如果流为空,则量化被认为是虚假满足,并且始终为true,不考虑 P(x)。
      参数:
      predicate - 一个非干扰无状态的谓词,应用于此流的元素
      返回:
      如果流中没有元素与提供的谓词匹配,或者流为空,则返回true,否则返回false
    • findFirst

      OptionalDouble findFirst()
      返回描述此流中第一个元素的OptionalDouble,如果流为空,则返回一个空的OptionalDouble。如果流没有遇到顺序,则可能返回任何元素。

      这是一个短路终端操作

      返回:
      描述此流中第一个元素的OptionalDouble,如果流为空则返回一个空的OptionalDouble
    • findAny

      OptionalDouble findAny()
      返回描述此流中某个元素的OptionalDouble,如果流为空,则返回一个空的OptionalDouble

      这是一个短路终端操作

      此操作的行为明确是不确定的;它可以自由选择流中的任何元素。这是为了在并行操作中获得最大性能;代价是对相同源的多次调用可能不会返回相同的结果。(如果需要稳定的结果,请改用findFirst()。)

      返回:
      描述此流中某个元素的OptionalDouble,如果流为空则返回一个空的OptionalDouble
      参见:
    • boxed

      Stream<Double> boxed()
      返回由此流中的元素组成的Stream,转换为Double

      这是一个中间操作

      返回值:
      一个由此流的元素组成的Stream,每个元素都装箱为Double
    • builder

      static DoubleStream.Builder builder()
      返回一个DoubleStream的构建器。
      返回值:
      一个流构建器
    • empty

      static DoubleStream empty()
      返回一个空的顺序DoubleStream
      返回值:
      一个空的顺序流
    • of

      static DoubleStream of(double t)
      返回一个包含单个元素的顺序DoubleStream
      参数:
      t - 单个元素
      返回值:
      一个单例顺序流
    • of

      static DoubleStream of(double... values)
      返回一个顺序有序流,其元素为指定的值。
      参数:
      values - 新流的元素
      返回值:
      新流
    • iterate

      static DoubleStream iterate(double seed, DoubleUnaryOperator f)
      返回一个无限顺序有序的DoubleStream,通过将函数f迭代应用于初始元素seed而产生,生成由seedf(seed)f(f(seed))等组成的Stream

      DoubleStream中的第一个元素(位置0)将是提供的seed。对于n > 0,位置n的元素将是将函数f应用于位置n - 1的元素的结果。

      对一个元素应用f的操作在对后续元素应用f的操作之前发生。对于任何给定元素,操作可能在库选择的任何线程中执行。

      参数:
      seed - 初始元素
      f - 要应用于前一个元素以生成新元素的函数
      返回值:
      一个新的顺序DoubleStream
    • iterate

      static DoubleStream iterate(double seed, DoublePredicate hasNext, DoubleUnaryOperator next)
      返回一个顺序有序的DoubleStream,通过将给定的next函数迭代应用于初始元素,条件是满足给定的hasNext谓词。流在hasNext谓词返回false时终止。

      DoubleStream.iterate应该产生与相应的for循环产生的元素序列相同的元素:

      
           for (double index=seed; hasNext.test(index); index = next.applyAsDouble(index)) {
               ...
           }
       

      如果hasNext谓词在种子值上不成立,则生成的序列可能为空。否则,第一个元素将是提供的seed值,下一个元素(如果存在)将是将next函数应用于seed值的结果,依此类推,直到hasNext谓词指示流应终止。

      hasNext谓词应用于一个元素的操作在将next函数应用于该元素之前发生。将next函数应用于一个元素的操作在将hasNext谓词应用于后续元素之前发生。对于任何给定元素,操作可能在库选择的任何线程中执行。

      参数:
      seed - 初始元素
      hasNext - 应用于元素以确定流何时终止的谓词
      next - 要应用于前一个元素以生成新元素的函数
      返回值:
      一个新的顺序DoubleStream
      自 JDK 版本:
      9
    • generate

      static DoubleStream generate(DoubleSupplier s)
      返回一个无限顺序无序流,其中每个元素由提供的DoubleSupplier生成。这适用于生成常量流、随机元素流等。
      参数:
      s - 生成元素的DoubleSupplier
      返回值:
      一个新的无限顺序无序DoubleStream
    • concat

      static DoubleStream concat(DoubleStream a, DoubleStream b)
      创建一个惰性连接的流,其元素是第一个流的所有元素,后跟第二个流的所有元素。如果两个输入流都是有序的,则生成的流是有序的,如果其中一个输入流是并行的,则生成的流是并行的。当关闭生成的流时,会调用两个输入流的关闭处理程序。

      此方法操作两个输入流,并将每个流绑定到其源。因此,对输入流源的后续修改可能不会反映在连接的流结果中。

      API 注释:
      为了保留优化机会,此方法将每个流绑定到其源,并仅接受两个流作为参数。例如,如果已知每个输入流源的确切大小,则可以计算连接流源的确切大小。要连接更多流而不绑定,或者避免嵌套调用此方法,请尝试创建流的流,并使用恒等函数进行扁平映射,例如:
      
           DoubleStream concat = Stream.of(s1, s2, s3, s4).flatMapToDouble(s -> s);
       
      实现注释:
      在从重复连接构造流时要小心。访问深度连接流的元素可能导致深度调用链,甚至StackOverflowError
      参数:
      a - 第一个流
      b - 第二个流
      返回值:
      两个输入流的连接