【jdk1.8特性】之Stream(下)

笔者日常 Stream知识点真的是…太多了!!!


声明 由于Stream知识极多,所以本人将其分为两个部分进行学习。

Stream(上)主要学习的内容有:
本文所学习的知识
Stream(下)主要学习的内容有:
在这里插入图片描述


Stream学习(下)之.collect(…)

  • .collect之Collectors.averagingInt、Collectors.averagingLong、Collectors.averagingDouble:统计Stream<T>流中, (根据)每个元素T得到的类型为int/long/double的数值的平均值。

    示例:

    /**
     * 统计Stream<T>流中, (根据)每个元素T得到的类型为int/long/double的数值的平均值。
     *
     * 注:统计结果为Double。
     *
     * 注:Stream的collect方法,签名为:
     *       <R, A> R collect(Collector<? super T, A, R> collector)
     *
     * 注:Collectors的caveragingLong方法,签名为:
     *       Collector<T, ?, Double> averagingInt(ToIntFunction<? super T> mapper)
     *
     * 注:Collectors的caveragingLong方法,签名为:
     *       Collector<T, ?, Double> averagingLong(ToLongFunction<? super T> mapper)
     *
     * 注:Collectors的caveragingLong方法,签名为:
     *       Collector<T, ?, Double> averagingDouble(ToDoubleFunction<? super T> mapper)
     *
     * 注:当前stream元素类型为T。
     *
     * 注:由于计算机二进制存数的问题,返回的double值可能存在误差。
     *
     * 建议:尽量少用此方法,如果非要用的话,建议用在那些对精度要求不高的场景下,且对结果进行舍入。
     */
    @Test
    public void test27_0() {
        // 数据准备
        List<Staff> tmpList = Lists.newArrayList(
                Staff.builder().name("张三").age(18).workStartTimestamp(1L).faceScore(99.9D).build(),
                Staff.builder().name("李四").age(24).workStartTimestamp(2L).faceScore(89.2D).build(),
                Staff.builder().name("王五").age(45).workStartTimestamp(3L).faceScore(68.6D).build()
        );
    
        // Collectors.averagingInt进行统计
        Double averageOne = tmpList.parallelStream().collect(
                // -> 根据Int值统计出平均值Double的统计器
                Collectors.averagingInt(
                        x -> x == null ? 0 : x.getAge()
                )
    
        );
        // 输出: 29.0
        System.out.println(averageOne);
    
        // Collectors.averagingLong进行统计
        Double averageTwo = tmpList.parallelStream().collect(
                // -> 根据Long值统计出平均值Double的统计器
                Collectors.averagingLong(
                        x -> x == null ? 0L : x.getWorkStartTimestamp()
                )
        );
        // 输出: 2.0
        System.out.println(averageTwo);
    
        // Collectors.averagingDouble进行统计
        Double averageThree = tmpList.parallelStream().collect(
                // -> 根据Double值统计出平均值Double的统计器
                Collectors.averagingDouble(
                        x -> x == null ? 0D : x.getFaceScore()
                )
        );
        // 输出: 85.90000000000002
        // 注:由于计算机二进制存数的问题,返回的double值可能存在误差, 如:这里理
        //    论上应返回85.9, 但是实际上返回的是85.90000000000002
        System.out.println(averageThree);
    }
    
  • .collect之Collectors.collectingAndThen:先按照Collectors对Stream<T>流中的元素进行统计(得到R), 再利用Function<R,RR>得到并返回RR。

    示例:

    /**
     * 先按照Collectors对Stream<T>流中的元素进行统计(得到R), 再利用Function<R,RR>得到并返回RR。
     * 即:对流的元素先Collector<T,A,R> downstream,再对得到的结果进行Function<R,RR> finisher,最后返回RR。
     *
     * 注:Stream的collect方法,签名为:
     *       <R, A> R collect(Collector<? super T, A, R> collector)
     *
     * 注:Collectors的collectingAndThen方法,签名为:
     *       Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream,
     *                                           Function<R,RR> finisher)
     *
     * 注:当前stream类型为T。
     */
    @Test
    public void test27_1() {
        // 数据准备
        List<Staff> tmpList = Lists.newArrayList(
                Staff.builder().name("张三").age(18).workStartTimestamp(1L).faceScore(99.9D).build(),
                Staff.builder().name("李四").age(25).workStartTimestamp(2L).faceScore(89.2D).build(),
                Staff.builder().name("王五").age(40).workStartTimestamp(3L).faceScore(68.7D).build()
        );
    
        // 为便于理解,这里 先编写一个Function<R,RR> finisher
        Function<Set<Staff>, Integer> function = Set::size;
    
        // 先Collector<T,A,R> downstream,再Function<R,RR> finisher,最后返回RR。
        Integer size = tmpList.parallelStream().collect(
                Collectors.collectingAndThen(
                        Collectors.toSet(),
                        function
                )
        );
        // 输出: 3
        System.out.println(size);
    }
    
  • .collect之Collectors.counting:对stream中的元素进行计数。

    示例:

    /**
     * 对stream中的元素进行计数。
     *
     * 注:Stream的collect方法,签名为:
     *       <R, A> R collect(Collector<? super T, A, R> collector)
     *
     * 注:Collectors的counting方法,签名为:
     *       Collector<T, ?, Long> counting()
     *
     * 注:当前stream类型为T。
     */
    @Test
    public void test27_2() {
        // 数据准备
        List<Staff> tmpList = Lists.newArrayList(
                Staff.builder().name("张三").age(18).workStartTimestamp(1L).faceScore(99.9D).build(),
                Staff.builder().name("李四").age(25).workStartTimestamp(2L).faceScore(89.2D).build(),
                Staff.builder().name("王五").age(40).workStartTimestamp(3L).faceScore(68.7D).build()
        );
        @SuppressWarnings("all")
        // 对stream中的元素进行计数。 等价于Stream的count()方法。
                Long count = tmpList.parallelStream().collect(
                Collectors.counting()
        );
        // 输出: 3
        System.out.println(count);
    }
    
  • .collect之Collectors.groupingBy:对stream中的元素进行分组。

    • 用法一: 先通过classifier,计算每个元素对应的key,然后再通过Collectors的groupingBy方法,按key值分组,得到并返回Map<K, List<T>>。
      示例:

      /**
       * 对stream中的元素进行分组:
       *     先通过classifier,计算每个元素对应的key,然后再通过Collectors的
       *     groupingBy方法,按key值分组,得到并返回Map<K, List<T>>
       *
       * 注:Stream的collect方法,签名为:
       *       <R, A> R collect(Collector<? super T, A, R> collector)
       *
       * 注:Collectors的重载groupingBy方法,(本次示例的方法的)签名为:
       *       Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier)
       *    追注:此方法内部调用的实际是groupingBy(classifier, HashMap::new, toList())方法
       * 
       * 注:此方法返回的Map实现是非线程安全的,如果需要返回线程安全的Map实现,可使用(使用方式几乎一致):
       *         Collector<T, ?, ConcurrentMap<K, List<T>>> groupingByConcurrent(Function<? super T, ? extends K> classifier)
       *
       * 注: 不论是串行stream,还是并行parallelStream,对于groupingBy(或groupingByConcurrent)本身来说,是线程安全的。
       *
       * 注:当前stream类型为T。
       *
       *
       */
      @Test
      public void test27_3() {
          // 数据准备
          List<Staff> tmpList = Lists.newArrayList(
                  Staff.builder().name("张三1").age(18).build(),
                  Staff.builder().name("张三2").age(15).build(),
                  Staff.builder().name("李四1").age(25).build(),
                  Staff.builder().name("李四2").age(23).build(),
                  Staff.builder().name("王五1").age(55).build(),
                  Staff.builder().name("王五2").age(40).build()
          );
      
          // 为便于理解,这里 先编写一个Function<? super T, ? extends K> classifier
          // 这个classifier的作用是: 根据元素T,返回其对应的K, 然后Collectors.groupingBy会根据K,
          // 将stream中的元素按键值对分组为Map<K, List<T>
          Function<Staff, String> function = x -> x.getName() == null ? "" : x.getName().substring(0, 1);
      
          // 使用Collectors.groupingBy,按照(通过Function得到的)key进行分组,得到并返回Map<K, List<T>>
          Map<String, List<Staff>> resultMap = tmpList.parallelStream().collect(
                  Collectors.groupingBy(function)
          );
      
          // 输出(为方便观察,本人简单整理了一下输出结果):
          // {
          //   张=[
          //       Staff(name=张三1, age=18, staffNo=null, faceScore=null, workStartTimestamp=null),
          //       Staff(name=张三2, age=15, staffNo=null, faceScore=null, workStartTimestamp=null)
          //      ],
          //
          //   王=[
          //       Staff(name=王五1, age=55, staffNo=null, faceScore=null, workStartTimestamp=null),
          //       Staff(name=王五2, age=40, staffNo=null, faceScore=null, workStartTimestamp=null)
          //      ],
          //
          //   李=[
          //       Staff(name=李四1, age=25, staffNo=null, faceScore=null, workStartTimestamp=null),
          //       Staff(name=李四2, age=23, staffNo=null, faceScore=null, workStartTimestamp=null)
          //      ]
          // }
          System.out.println(resultMap);
      }
      
    • 用法二: 先通过classifier,计算每个元素对应的key,然后根据key进行分组,然后对每组的元素T进行downstream统计,得到每组的结果D, 最终返回Map<K, D>。
      :先通过classifier得到Map<K, List<T>>,再通过对每个List<T>进行downstream统计,最终得到Map<K, D>。

      示例:

      /**
       * 对stream中的元素进行分组:
       *     先通过classifier,计算每个元素对应的key,然后根据key进行分组,然后对每组的
       *     元素T进行downstream统计,得到每组的结果D, 最终返回Map<K, D>。
       *     即:先通过classifier得到Map<K, List<T>>,再通过
       *        对每个List<T>进行downstream统计,最终得到Map<K, D>。
       *
       * 注:Stream的collect方法,签名为:
       *       <R, A> R collect(Collector<? super T, A, R> collector)
       *
       * 注:Collectors的重载groupingBy方法,(本次示例的方法的)签名为:
       *       Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
       *                                             Collector<? super T, A, D> downstream)
       *    追注:此方法内部调用的实际是groupingBy(classifier, HashMap::new, downstream)方法
       * 
       * 注:此方法返回的Map实现是非线程安全的,如果需要返回线程安全的Map实现,可使用(使用方式几乎一致):
       *         Collector<T, ?, ConcurrentMap<K, D>> groupingByConcurrent(Function<? super T, ? extends K> classifier,
       *                                                                   Collector<? super T, A, D> downstream)
       * 
       * 注: 不论是串行stream,还是并行parallelStream,对于groupingBy(或groupingByConcurrent)本身来说,是线程安全的。
       * 
       * 注:当前stream类型为T。
       */
      @Test
      public void test27_4() {
          // 数据准备
          List<Staff> tmpList = Lists.newArrayList(
                  Staff.builder().name("张三1").age(18).build(),
                  Staff.builder().name("张三2").age(15).build(),
                  Staff.builder().name("张三3").age(11).build(),
                  Staff.builder().name("李四1").age(25).build(),
                  Staff.builder().name("李四2").age(23).build(),
                  Staff.builder().name("王五1").age(55).build(),
                  Staff.builder().name("王五2").age(40).build()
          );
      
          // 为便于理解,这里 先编写一个Function<? super T, ? extends K> classifier
          Function<Staff, String> function = x -> x.getName() == null ? "" : x.getName().substring(0, 1);
      
          // 使用Collectors.groupingBy,按照(通过Function得到的)key进行分组并对各组元素进行统计,得到并返回Map<K, D>
          Map<String, Long> resultMap = tmpList.parallelStream().collect(
                  Collectors.groupingBy(function, Collectors.counting())
          );
      
          // 输出: {张=3, 王=2, 李=2}
          System.out.println(resultMap);
      }
      
    • 用法三: 先通过classifier,计算每个元素对应的key,然后根据key进行分组,然后对每组的元素T进行downstream统计,得到每组的结果D。最终返回Map<K, D>。Map<K, D>即对应Supplier<M> mapFactory中的M,换句话说,返回的Map容器由mapFactory进行提供。
      :先通过classifier得到Map<K, List<T>>,再通过对每个List<T>进行downstream统计,并将K和D放入由mapFactory提供的M中(即:mapFactory提供的Map中),并进行返回。

      示例:

      /**
       * 对stream中的元素进行分组:
       *     先通过classifier,计算每个元素对应的key,然后根据key进行分组,然后对每组的
       *     元素T进行downstream统计,得到每组的结果D。最终返回Map<K, D>。Map<K, D>
       *     即对应Supplier<M> mapFactory中的M,换句话说:返回的Map容器由mapFactory进行提供。
       *     即:先通过classifier得到Map<K, List<T>>,再通过
       *        对每个List<T>进行downstream统计,并将K和D放入由mapFactory提供
       *        的M中(即:mapFactory提供的Map中),并进行返回。
       *
       * 注:Stream的collect方法,签名为:
       *       <R, A> R collect(Collector<? super T, A, R> collector)
       *
       * 注:Collectors的重载groupingBy方法,(本次示例的方法的)签名为:
       *       Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,
       *                                     Supplier<M> mapFactory,
       *                                     Collector<? super T, A, D> downstream)
       * 注:此方法返回的Map实现是非线程安全的,如果需要返回线程安全的Map实现,可使用(使用方式几乎一致):
       *         Collector<T, ?, M> groupingByConcurrent(Function<? super T, ? extends K> classifier,
       *                                                 Supplier<M> mapFactory,
       *                                                 Collector<? super T, A, D> downstream)
       * 
       * 注: 不论是串行stream,还是并行parallelStream,对于groupingBy(或groupingByConcurrent)本身来说,是线程安全的。
       * 
       * 注:当前stream类型为T。
       */
      @Test
      public void test27_5() {
          // 数据准备
          List<Staff> tmpList = Lists.newArrayList(
                  Staff.builder().name("张三1").age(18).build(),
                  Staff.builder().name("张三2").age(15).build(),
                  Staff.builder().name("张三3").age(11).build(),
                  Staff.builder().name("李四1").age(25).build(),
                  Staff.builder().name("李四2").age(23).build(),
                  Staff.builder().name("王五1").age(55).build(),
                  Staff.builder().name("王五2").age(40).build()
          );
      
          // 为便于理解,这里 先编写一个Function<? super T, ? extends K> classifier
          Function<Staff, String> function = x -> x.getName() == null ? "" : x.getName().substring(0, 1);
      
      
          //  Supplier<M> mapFactory
          Supplier<TreeMap<String, Long>> mapFactory = TreeMap::new;
      
          // 使用Collectors.groupingBy,按照(通过Function得到的)key进行分组并对各组元素进行统计,得到并返回Map<K, D>
          Map<String, Long> resultMap = tmpList.parallelStream().collect(
                  Collectors.groupingBy(function, mapFactory, Collectors.counting())
          );
      
          // 输出: {张=3, 王=2, 李=2}
          System.out.println(resultMap);
      }
      
  • .collect之Collectors.joining:字符串拼接。

    • 用法一:对Stream<String>中的元素直接进行拼接。
      示例:
      /**
       * 对Stream<String>中的元素直接进行拼接。
       *
       * 注:Stream的collect方法,签名为:
       *       <R, A> R collect(Collector<? super T, A, R> collector)
       *
       * 注:Collectors的joining方法,签名为:
       *         Collector<CharSequence, ?, String> joining()
       *
       * 注:当前stream类型为T。
       */
      @Test
      public void test27_6() {
          // 数据准备
          List<String> tmpList = Lists.newArrayList("A","B","C","D","E");
      
          String resultStr = tmpList.parallelStream().collect(
                  Collectors.joining()
          );
      
          // 输出: ABCDE
          System.out.println(resultStr);
      }
      
    • 用法二:对Stream<String>中的元素以delimiter为分隔符进行拼接。
      示例:
      /**
       * 对Stream<String>中的元素以delimiter为分隔符进行拼接。
       *
       * 注:Stream的collect方法,签名为:
       *       <R, A> R collect(Collector<? super T, A, R> collector)
       *
       * 注:Collectors的joining方法,签名为:
       *         Collector<CharSequence, ?, String> joining(CharSequence delimiter)
       *
       * 注:当前stream类型为T。
       */
      @Test
      public void test27_7() {
          // 数据准备
          List<String> tmpList = Lists.newArrayList("A","B","C","D","E");
      
          String resultStr = tmpList.parallelStream().collect(
                  Collectors.joining("-")
          );
      
          // 输出: A-B-C-D-E
          System.out.println(resultStr);
      }
      
    • 用法三:以delimiter为分隔符,以prefix为前缀,以suffix为后缀,对Stream<String>中的元素进行拼接。
      示例:
      /**
       * 以delimiter为分隔符,以prefix为前缀,以suffix为后缀,对Stream<String>中的元素进行拼接。
       *
       * 注:Stream的collect方法,签名为:
       *       <R, A> R collect(Collector<? super T, A, R> collector)
       *
       * 注:Collectors的joining方法,签名为:
       *         Collector<CharSequence, ?, String> joining(CharSequence delimiter,
       *                                                    CharSequence prefix,
       *                                                    CharSequence suffix)
       *
       * 注:当前stream类型为T。
       */
      @Test
      public void test27_8() {
          // 数据准备
          List<String> tmpList = Lists.newArrayList("A","B","C","D","E");
      
          String resultStr = tmpList.parallelStream().collect(
                  Collectors.joining("-", "[", "]")
          );
      
          // 输出: [A-B-C-D-E]
          System.out.println(resultStr);
      }
      
  • .collect之Collectors.mapping:先以mapper将Stream<T>转换为Stream<U>,再用downstream对Stream<U>进行统计。

    提示:collect(mapping())能做的事,.map().collect()都能做;我们一般都使用.map().collect(),而不使用collect(mapping())。

    示例:

    /**
     * 先以mapper将Stream<T>转换为Stream<U>,再用downstream对Stream<U>进行统计。
     *
     * 提示:collect(mapping())能做的事,.map().collect()都能做;我们一般都
     *     使用.map().collect(),而不使用collect(mapping())。
     *
     * 注:Stream的collect方法,签名为:
     *       <R, A> R collect(Collector<? super T, A, R> collector)
     *
     * 注:Collectors的mapping方法,签名为:
     *         Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper,
     *                                    Collector<? super U, A, R> downstream)
     *
     * 注:当前stream类型为T。
     */
    @Test
    public void test27_9() {
        // 数据准备
        List<Staff> tmpList = Lists.newArrayList(
                Staff.builder().name("张三").age(18).workStartTimestamp(1L).faceScore(99.9D).build(),
                Staff.builder().name("李四").age(25).workStartTimestamp(2L).faceScore(89.2D).build(),
                Staff.builder().name("王五").age(40).workStartTimestamp(3L).faceScore(68.7D).build()
        );
    
        // 为便于理解,这里 先编写一个Function<? super T, ? extends U> mapper
        Function<Staff, String> function = Staff::getName;
        @SuppressWarnings("all")
        String resultStr = tmpList.parallelStream().collect(
                Collectors.mapping(
                        function,
                        Collectors.joining("&")
                )
        );
        // 输出: 张三&李四&王五
        System.out.println(resultStr);
    
        /// 以.map().collect()的方式来实现的话,是这样的:
        String resultStr2 =  tmpList.parallelStream().map(Staff::getName).collect(Collectors.joining("&"));
        // 输出: 张三&李四&王五
        System.out.println(resultStr2);
    }
    
  • .collect之Collectors.maxBy、Collectors.minBy:根据比较器,筛选出Stream<T>中最大、最小的元素。

    示例:

    /**
     * 根据比较器,筛选出Stream<T>中最大、最小的元素。
     *
     * 注:推荐使用.max()、.min()的方式,而非.collect(Collectors.maxBy())、.collect(Collectors.minBy())
     *
     * 注:Stream的collect方法,签名为:
     *       <R, A> R collect(Collector<? super T, A, R> collector)
     *
     * 注:Collectors的maxBy方法,签名为:
     *         Collector<T, ?, Optional<T>> maxBy(Comparator<? super T> comparator)
     *
     * 注:Collectors的maxBy方法,签名为:
     *         Collector<T, ?, Optional<T>> minBy(Comparator<? super T> comparator)
     *
     * 注:当前stream类型为T。
     */
    @Test
    @SuppressWarnings("all")
    public void test27_10() {
        // 数据准备
        List<Integer> tmpList = Lists.newArrayList(3, 5, 1, 7, 9);
    
        // 比较器准备
        Comparator<Integer> comparator = Comparator.comparingInt(x -> x);
    
        // -> 最大值
        // 等价于: tmpList.parallelStream().max(comparator)
        Optional<Integer> maxResult = tmpList.parallelStream().collect(
                Collectors.maxBy(comparator)
        );
        // 输出: 9
        maxResult.ifPresent(System.out::println);
    
        // -> 最小值
        // 等价于: tmpList.parallelStream().min(comparator)
        Optional<Integer> minResult = tmpList.parallelStream().collect(
                Collectors.minBy(comparator)
        );
        // 输出: 1
        minResult.ifPresent(System.out::println);
    }
    
  • .collect之Collectors.partitioningBy:(按key为true或false进行)分组。

    • 用法一: 将Stream中的元素,分为两组: predicate通过的分到key为true的组,否者分到key为false的组,最后得到并返回Map<Boolean, List<T>>>。
      示例:
      /**
       * 将Stream<T>中的元素,分为两组: predicate通过的分到key为true的组,否者分到key为false的组,
       * 最后得到并返回Map<Boolean, List<T>>>。
       *
       * 注:Stream的collect方法,签名为:
       *       <R, A> R collect(Collector<? super T, A, R> collector)
       *
       * 注:Collectors的partitioningBy方法,签名为:
       *         Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate)
       *    追注:此方法与groupingBy方法类似,也是分组。不过此方法是根据predicate将元素分为key为tru/false两组;
       *        而groupingBy是根据Function<? super T, ? extends K> classifier来进行的分组。
       *
       * 注:当前stream类型为T。
       */
      @Test
      public void test27_11() {
          // 数据准备
          List<Integer> tmpList = Lists.newArrayList(3, 5, 1, 7, 9);
      
          // 准备一个比较器
          Predicate<Integer> predicate = x -> x > 6;
      
          // -> 最大值
          Map<Boolean, List<Integer>> resultMap = tmpList.parallelStream().collect(
                  Collectors.partitioningBy(predicate)
          );
          // 输出: {false=[3, 5, 1], true=[7, 9]}
          System.out.println(resultMap);
      }
      
    • 用法二: 将Stream<T>中的元素,分为两组: predicate通过的分到key为true的组,否者分到key为false的组,然后通过downstream再对每组进行统计(得到统计结果D),最后得到并返回Map<Boolean, D>。
      示例:
      /**
       * 将Stream<T>中的元素,分为两组: predicate通过的分到key为true的组,否者分到key为false的组,
       * 然后通过downstream再对每组进行统计(得到统计结果D),最后得到并返回Map<Boolean, D>。
       *
       * 注:Stream的collect方法,签名为:
       *       <R, A> R collect(Collector<? super T, A, R> collector)
       *
       * 注:Collectors的partitioningBy方法,签名为:
       *         Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,
       *                                                         Collector<? super T, A, D> downstream)
       *    追注:此方法与groupingBy方法类似,类比着进行理解即可。
       *
       * 注:当前stream类型为T。
       */
      @Test
      public void test27_12() {
          // 数据准备
          List<Integer> tmpList = Lists.newArrayList(3, 5, 1, 7, 9);
      
          // 准备一个比较器
          Predicate<Integer> predicate = x -> x > 6;
      
          // -> 最大值
          Map<Boolean, Long> resultMap = tmpList.parallelStream().collect(
                  Collectors.partitioningBy(
                          predicate,
                          Collectors.counting()
                  )
          );
          // 输出: {false=3, true=2}
          System.out.println(resultMap);
      }
      
  • .collect之Collectors.reducing:对Stream中的元素进行归并。

    提示: 串行流下的reduce与并行流下的reduce可能结果不一样,如果不太熟悉的话,建议使用stream的reduce(),而不使用.stream().collect(Collectors.reducing())。

    示例:

    /**
     * 对Stream<T>中的元素进行归并。
     * 提示:串行流下的reduce与并行流下的reduce可能结果不一样,如果不太熟悉的话,建议
     *      使用stream的reduce(),而不使用.stream().collect(Collectors.reducing())。
     *
     * 注:Stream的collect方法,签名为:
     *       <R, A> R collect(Collector<? super T, A, R> collector)
     *
     * 注:Collectors的reducing方法,签名为:
     *        Collector<T, ?, Optional<T>> reducing(BinaryOperator<T> op)
     *
     * 注:当前stream类型为T。
     *
     * 声明:在stream的collect()方法内部进行reduce的,总共有下述三种方法
     *      Collector<T,?,Optional<T>> reducing(BinaryOperator<T> op)
     *      Collector<T,?,T> reducing(T identity, BinaryOperator<T> op)
     *      Collector<T,?,U> reducing(U identity, Function<? super T,? extends U> mapper, BinaryOperator<U> op),
     *      此这里只示例第一种。
     */
    @Test
    public void test27_13() {
        // 数据准备
        List<Integer> tmpList = Lists.newArrayList(3, 5, 1, 7, 9);
    
        BinaryOperator<Integer> binaryOperator = Integer::sum;
        // -> 进行归并
        @SuppressWarnings("all")
        Optional<Integer> result = tmpList.stream().collect(
                Collectors.reducing(binaryOperator)
        );
        // 输出: 25
        result.ifPresent(System.out::println);
    }
    
  • .collect之Collectors.summarizingInt、Collectors.summarizingLong、Collectors.summarizingDouble:对Stream<T>中的元素T“对应”的int/long/double值进行统计,并获得一个统计对象;通过此对象可以获得具体的统计信息(如:最大值、最小值、平均值、总和、数量)。

    示例:

    /**
     * 对Stream<T>中的元素T“对应”的int/long/double值进行统计,并获得一个统计对象;
     * 通过此对象可以获得具体的统计信息(如:最大值、最小值、平均值、总和、数量)。
     *
     * 注:Stream的collect方法,签名为:
     *       <R, A> R collect(Collector<? super T, A, R> collector)
     *
     * 注:Collectors的summarizingInt方法,签名为:
     *        Collector<T, ?, IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper)
     *
     * 注:Collectors的summarizingLong方法,签名为:
     *        Collector<T, ?, LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper)
     *
     * 注:Collectors的summarizingDouble方法,签名为:
     *        Collector<T, ?, DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper)
     *
     * 注:当前stream类型为T。
     *
     */
    @Test
    public void test27_14() {
        // 数据准备
        List<Staff> tmpList = Lists.newArrayList(
                Staff.builder().name("张三").age(18).workStartTimestamp(123L).faceScore(99.9D).build(),
                Staff.builder().name("李四").age(45).workStartTimestamp(456L).faceScore(66.6D).build(),
                Staff.builder().name("王五").age(24).workStartTimestamp(789L).faceScore(33.3D).build()
        );
    
        /// -> summarizingInt示例
        // 编写mapper,使用此mapper,能根据Stream<T>中的元素T,获取到对应的int值
        ToIntFunction<Staff> intMapper = Staff::getAge;
        // 采集数据,获得统计信息 对象
        IntSummaryStatistics intResult = tmpList.parallelStream().collect(
                Collectors.summarizingInt(intMapper)
        );
        // 输出: IntSummaryStatistics{count=3, sum=87, min=18, average=29.000000, max=45}
        System.out.println(intResult);
    
        /// -> summarizingLong示例
        // 编写mapper,使用此mapper,能根据Stream<T>中的元素T,获取到对应的int值
        ToLongFunction<Staff> longMapper = Staff::getWorkStartTimestamp;
        // 采集数据,获得统计信息 对象
        LongSummaryStatistics longResult = tmpList.parallelStream().collect(
                Collectors.summarizingLong(longMapper)
        );
        // 输出: LongSummaryStatistics{count=3, sum=1368, min=123, average=456.000000, max=789}
        System.out.println(longResult);
    
        /// -> summarizingDouble示例
        // 编写mapper,使用此mapper,能根据Stream<T>中的元素T,获取到对应的double值
        ToDoubleFunction<Staff> doubleMapper = Staff::getFaceScore;
        // 采集数据,获得统计信息 对象
        DoubleSummaryStatistics doubleResult = tmpList.parallelStream().collect(
                Collectors.summarizingDouble(doubleMapper)
        );
        // 输出: DoubleSummaryStatistics{count=3, sum=199.800000, min=33.300000, average=66.600000, max=99.900000}
        System.out.println(doubleResult);
    }
    
  • .collect之Collectors.summingInt、Collectors.summingLong、Collectors.summingDouble:求和。

    提示:建议使用.mapToInt().sum(),而不使用.collect(Collectors.summingInt());建议使用.mapToLong().sum(),而不使用.collect(Collectors.summingLong());建议使用.mapToDouble().sum(),而不使用.collect(Collectors.summingDouble())。
    示例:

    /**
     * 对Stream<T>中的元素T“对应”的int/long/double值进行求和。
     *
     * 建议使用.mapToInt().sum(),而不使用.collect(Collectors.summingInt())
     * 建议使用.mapToLong().sum(),而不使用.collect(Collectors.summingLong())
     * 建议使用.mapToDouble().sum(),而不使用.collect(Collectors.summingDouble())
     *
     * 注:Stream的collect方法,签名为:
     *       <R, A> R collect(Collector<? super T, A, R> collector)
     *
     * 注:Collectors的summarizingInt方法,签名为:
     *        Collector<T, ?, Integer> summingInt(ToIntFunction<? super T> mapper)
     *
     * 注:Collectors的summarizingLong方法,签名为:
     *        Collector<T, ?, LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper)
     *
     * 注:Collectors的summarizingDouble方法,签名为:
     *        Collector<T, ?, DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper)
     *
     * 注:当前stream类型为T。
     *
     */
    @Test
    @SuppressWarnings("all")
    public void test27_15() {
        // 数据准备
        List<Staff> tmpList = Lists.newArrayList(
                Staff.builder().name("张三").age(18).workStartTimestamp(123L).faceScore(99.9D).build(),
                Staff.builder().name("李四").age(45).workStartTimestamp(456L).faceScore(66.6D).build(),
                Staff.builder().name("王五").age(24).workStartTimestamp(789L).faceScore(33.3D).build()
        );
    
        /// -> summingInt示例
        // 编写mapper,使用此mapper,能根据Stream<T>中的元素T,获取到对应的int值
        ToIntFunction<Staff> intMapper = Staff::getAge;
        // Integer求和
        Integer intResult = tmpList.parallelStream().collect(
                Collectors.summingInt(intMapper)
        );
        // 输出: 87
        System.out.println(intResult);
    
        /// -> summingLong示例
        // 编写mapper,使用此mapper,能根据Stream<T>中的元素T,获取到对应的int值
        ToLongFunction<Staff> longMapper = Staff::getWorkStartTimestamp;
        // Long求和
        Long longResult = tmpList.parallelStream().collect(
                Collectors.summingLong(longMapper)
        );
        // 输出: 1368
        System.out.println(longResult);
    
        /// -> summingDouble示例
        // 编写mapper,使用此mapper,能根据Stream<T>中的元素T,获取到对应的double值
        ToDoubleFunction<Staff> doubleMapper = Staff::getFaceScore;
        //  Double求和
        Double doubleResult = tmpList.parallelStream().collect(
                Collectors.summingDouble(doubleMapper)
        );
        // 输出: 199.8
        System.out.println(doubleResult);
    }
    
  • .collect之Collectors.toList:将Stream<T>转换为一个集合List<T>。

    提示:实际上转换成的是ArrayList<T>。
    示例:

    /**
     * 将Stream<T>转换为一个集合List<T>。
     * 注:实际上转换成的是ArrayList<T>
     *
     * 注:Stream的collect方法,签名为:
     *       <R, A> R collect(Collector<? super T, A, R> collector)
     *
     * 注:Collectors的toList方法,签名为:
     *        Collector<T, ?, List<T>> toList()
     *
     * 注:当前stream类型为T。
     *
     */
    @Test
    public void test27_16() {
        // 数据准备
        Stream<Staff> s = Stream.of(
                Staff.builder().name("张三").age(18).workStartTimestamp(123L).faceScore(99.9D).build(),
                Staff.builder().name("李四").age(45).workStartTimestamp(456L).faceScore(66.6D).build(),
                Staff.builder().name("王五").age(24).workStartTimestamp(789L).faceScore(33.3D).build()
        );
        // 将String<T>转换为集合List<T>
        List<Staff> list = s.parallel().collect(
                Collectors.toList()
        );
        // 输出(为方便观察,本人简单整理了一下输出结果):
        // [
        //  Staff(name=张三, age=18, staffNo=null, faceScore=99.9, workStartTimestamp=123),
        //  Staff(name=李四, age=45, staffNo=null, faceScore=66.6, workStartTimestamp=456),
        //  Staff(name=王五, age=24, staffNo=null, faceScore=33.3, workStartTimestamp=789)
        // ]
        System.out.println(list);
    }
    
  • .collect之Collectors.toSet:将Stream<T>转换为一个集合Set<T>。

    提示:实际上转换成的是HashSet<T>。
    示例:

    /**
     * 将Stream<T>转换为一个集合Set<T>。
     * 注:实际上转换成的是HashSet<T>。
     *
     * 注:Stream的collect方法,签名为:
     *       <R, A> R collect(Collector<? super T, A, R> collector)
     *
     * 注:Collectors的toSet方法,签名为:
     *        Collector<T, ?, Set<T>> toSet()
     *
     * 注:当前stream类型为T。
     *
     */
    @Test
    public void test27_17() {
        // 数据准备
        Stream<Staff> s = Stream.of(
                Staff.builder().name("张三").age(18).workStartTimestamp(123L).faceScore(99.9D).build(),
                Staff.builder().name("李四").age(45).workStartTimestamp(456L).faceScore(66.6D).build(),
                Staff.builder().name("王五").age(24).workStartTimestamp(789L).faceScore(33.3D).build()
        );
        // 将String<T>转换为集合List<T>
        Set<Staff> set = s.parallel().collect(
                Collectors.toSet()
        );
        // 输出(为方便观察,本人简单整理了一下输出结果):
        // [
        //  Staff(name=张三, age=18, staffNo=null, faceScore=99.9, workStartTimestamp=123),
        //  Staff(name=李四, age=45, staffNo=null, faceScore=66.6, workStartTimestamp=456),
        //  Staff(name=王五, age=24, staffNo=null, faceScore=33.3, workStartTimestamp=789)
        // ]
        System.out.println(set);
    }
    
  • .collect之Collectors.toCollection:将Stream转换为一个(自定义类型的)集合。

    示例:

    /**
     * 将Stream<T>转换为一个(自定义类型的)集合。
     *
     * 注:Stream的collect方法,签名为:
     *       <R, A> R collect(Collector<? super T, A, R> collector)
     *
     * 注:Collectors的toCollection方法,签名为:
     *        Collector<T, ?, C> toCollection(Supplier<C> collectionFactory)
     *
     * 注:当前stream类型为T。
     *
     */
    @Test
    public void test27_18() {
        // 数据准备
        Stream<Staff> s = Stream.of(
                Staff.builder().name("张三").age(18).workStartTimestamp(123L).faceScore(99.9D).build(),
                Staff.builder().name("李四").age(45).workStartTimestamp(456L).faceScore(66.6D).build(),
                Staff.builder().name("王五").age(24).workStartTimestamp(789L).faceScore(33.3D).build()
        );
    
        // 先实现Supplier<C>, Supplier<C>会提供一种集合容器。
        Supplier<LinkedList<Staff>> collectionFactory = LinkedList::new;
    
        // 将String<T>转换为集合LinkedList<T>
        LinkedList<Staff> linkedList = s.parallel().collect(
                Collectors.toCollection(collectionFactory)
        );
        // 输出(为方便观察,本人简单整理了一下输出结果):
        // [
        //  Staff(name=张三, age=18, staffNo=null, faceScore=99.9, workStartTimestamp=123),
        //  Staff(name=李四, age=45, staffNo=null, faceScore=66.6, workStartTimestamp=456),
        //  Staff(name=王五, age=24, staffNo=null, faceScore=33.3, workStartTimestamp=789)
        // ]
        System.out.println(linkedList);
    }
    
  • .collect之Collectors.toMap、Collectors.toConcurrentMap:将流转换为Map(或ConcurrentMap)。

  • 特别注意:筛选出来后(,调用Map#merge方法之前,需保证)value值不能为null,否者会报NPE。可详见源码java.util.Map(或其对应子类)的merge方法

  • 用法一: 将Stream<T>转换为一个Map, 在转换时若发现重复的key,那么会抛出异常。
    提示:这里示例的是toMap方法(转换为线程非安全的Map),对应的(转换为线程 安全的ConcurrentMap的)toConcurrentMap方法用法几乎是一样的。
    示例:

    /**
     * 将Stream<T>转换为一个Map, 在转换时若发现重复的key,那么会抛出异常。
     *
     * 提示:这里示例的是toMap方法(转换为线程非安全的Map),对应的(转换为线程
     *      安全的ConcurrentMap的)toConcurrentMap方法用法几乎是一样的。
     *
     * 特别注意:筛选出来后(,调用Map#merge方法之前,需保证)value值不能为null,否者会报NPE。可详见源码java.util.Map(或其对应子类)的merge方法。
     *
     * 注:Stream的collect方法,签名为:
     *       <R, A> R collect(Collector<? super T, A, R> collector)
     *
     * 注:Collectors的toMap方法,签名为:
     *        Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper)
     *        追注:此方式的toMap,要求key不能有重复的,否者会出错
     *            java.lang.IllegalStateException: java.lang.IllegalStateException: Duplicate key...
     *        追注:此方法内部调用的其实是:toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new);
     *
     * 注:Collectors的toConcurrentMap方法,签名为:
     *        Collector<T,?,ConcurrentMap<K,U>> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper)
     *        追注:用法与本示例几乎一样,不过toConcurrentMap是线程安全的。
     *        追注:此方式的toMap,要求key不能有重复的,否者会出错
     *            java.lang.IllegalStateException: java.lang.IllegalStateException: Duplicate key...
     *        追注:此方法内部调用的其实是:toConcurrentMap(keyMapper, valueMapper, throwingMerger(), ConcurrentHashMap::new)
     *
     * 注:当前stream类型为T。
     *
     */
    @Test
    public void test27_19() {
        // 数据准备
        Stream<Staff> s = Stream.of(
                Staff.builder().name("张三").age(18).workStartTimestamp(123L).faceScore(99.9D).build(),
                Staff.builder().name("李四").age(45).workStartTimestamp(456L).faceScore(66.6D).build(),
                Staff.builder().name("王五").age(24).workStartTimestamp(789L).faceScore(33.3D).build()
        );
    
        // 编写一个keyMapper,用于 根据元素T获取对应的key
        Function<Staff, String> keyMapper = Staff::getName;
    
        // 编写一个valueMapper,用于 根据元素T获取对应的value
        Function<Staff, Integer> valueMapper = Staff::getAge;
    
        // 将Stream<T>转换为Map
        Map<String, Integer> resultMap = s.collect(
                Collectors.toMap(keyMapper, valueMapper)
        );
    
        // 输出: {李四=45, 张三=18, 王五=24}
        System.out.println(resultMap);
    }
    
  • 用法二: 将Stream<T>转换为一个Map,在转换时若发现重复的key,那么会根据mergeFunction来决定该key的value是多少。
    提示:这里示例的是toMap方法(转换为线程非安全的Map),对应的(转换为线程安全的ConcurrentMap的)toConcurrentMap方法用法几乎是一样的。
    示例:

    /**
     * 将Stream<T>转换为一个Map, 在转换时若发现重复的key,那么会根据mergeFunction来决定该key的value是多少。
     *
     * 提示:这里示例的是toMap方法(转换为线程非安全的Map),对应的(转换为线程
     *      安全的ConcurrentMap的)toConcurrentMap方法用法几乎是一样的。
     *
     * 特别注意:筛选出来后(,调用Map#merge方法之前,需保证)value值不能为null,否者会报NPE。可详见源码java.util.Map(或其对应子类)的merge方法。
     *
     * 注:Stream的collect方法,签名为:
     *       <R, A> R collect(Collector<? super T, A, R> collector)
     *
     * 注:Collectors的toMap方法,签名为:
     *        Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction)
     *        追注:此方法内部调用的其实是:toMap(keyMapper, valueMapper, mergeFunction, HashMap::new)
     *
     * 注:Collectors的toConcurrentMap方法,签名为:
     *        Collector<T,?,ConcurrentMap<K,U>> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction)
     *        追注:用法与本示例几乎一样,不过toConcurrentMap是线程安全的。
     *        追注:此方法内部调用的其实是:toConcurrentMap(keyMapper, valueMapper, mergeFunction, ConcurrentHashMap::new)
     *
     * 注:当前stream类型为T。
     *
     */
    @Test
    public void test27_20() {
        // 数据准备
        Stream<Staff> s = Stream.of(
                Staff.builder().name("张三").age(18).workStartTimestamp(123L).faceScore(99.9D).build(),
                Staff.builder().name("张三").age(100).workStartTimestamp(123L).faceScore(99.9D).build(),
                Staff.builder().name("李四").age(45).workStartTimestamp(456L).faceScore(66.6D).build(),
                Staff.builder().name("王五").age(24).workStartTimestamp(789L).faceScore(33.3D).build()
        );
    
        // 编写一个keyMapper,用于 根据元素T获取对应的key
        Function<Staff, String> keyMapper = Staff::getName;
    
        // 编写一个valueMapper,用于 根据元素T获取对应的value
        Function<Staff, Staff> valueMapper = Function.identity();
    
        // 编写一个mergeFunction,用于 处理 key冲突时的逻辑
        BinaryOperator<Staff> mergeFunction = (Staff preStaff, Staff nextValue) -> {
            // 输出: oldStaff的name是[张三], age是[18]
            System.err.println("preStaff的name是[" + preStaff.getName() + "], age是[" + preStaff.getAge() + "]");
            // 输出: oldStaff的name是[张三], age是[100]
            System.err.println("nextValue的name是[" + nextValue.getName() + "], age是[" + nextValue.getAge() + "]");
            return nextValue;
        };
    
        // 将Stream<T>转换为Map
        Map<String, Staff> resultMap = s.collect(
                Collectors.toMap(keyMapper, valueMapper, mergeFunction)
        );
    
        // 输出(为方便观察,本人简单整理了一下输出结果):
        // {
        //  李四=Staff(name=李四, age=45, staffNo=null, faceScore=66.6, workStartTimestamp=456),
        //  张三=Staff(name=张三, age=100, staffNo=null, faceScore=99.9, workStartTimestamp=123),
        //  王五=Staff(name=王五, age=24, staffNo=null, faceScore=33.3, workStartTimestamp=789)
        // }
        System.out.println(resultMap);
    }
    
  • 用法三: 将Stream<T>转换为一个(由mapSupplier定义提供的)Map,在转换时若发现重复的key,那么会根据mergeFunction来决定该key的value是多少。
    提示:这里示例的是toMap方法(转换为线程非安全的Map),对应的(转换为线程安全的ConcurrentMap的)toConcurrentMap方法用法几乎是一样的。
    示例:

    /**
     * 将Stream<T>转换为一个(由mapSupplier定义提供的)Map, 在转换时若发现重复的key,
     * 那么会根据mergeFunction来决定该key的value是多少。
     *
     * 提示:这里示例的是toMap方法(转换为线程非安全的Map),对应的(转换为线程
     *      安全的ConcurrentMap的)toConcurrentMap方法用法几乎是一样的。
     *
     * 特别注意:筛选出来后(,调用Map#merge方法之前,需保证)value值不能为null,否者会报NPE。可详见源码java.util.Map(或其对应子类)的merge方法。
     *
     * 注:Stream的collect方法,签名为:
     *       <R, A> R collect(Collector<? super T, A, R> collector)
     *
     * 注:Collectors的toMap方法,签名为:
     *        Collector<T,?,M> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier)
     *
     * 注:Collectors的toConcurrentMap方法,签名为:
     *        Collector<T,?,M> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier)
     *        追注:用法与本示例几乎一样,不过toConcurrentMap是线程安全的。
     *
     * 注:当前stream类型为T。
     *
     */
    @Test
    public void test27_21() {
        // 数据准备
        Stream<Staff> s = Stream.of(
                Staff.builder().name("张三").age(18).workStartTimestamp(123L).faceScore(99.9D).build(),
                Staff.builder().name("张三").age(100).workStartTimestamp(123L).faceScore(99.9D).build(),
                Staff.builder().name("李四").age(45).workStartTimestamp(456L).faceScore(66.6D).build(),
                Staff.builder().name("王五").age(24).workStartTimestamp(789L).faceScore(33.3D).build()
        );
    
        // 编写一个keyMapper,用于 根据元素T获取对应的key
        Function<Staff, String> keyMapper = Staff::getName;
    
        // 编写一个valueMapper,用于 根据元素T获取对应的value
        Function<Staff, Integer> valueMapper = Staff::getAge;
    
        // 编写一个mergeFunction,用于 处理 key冲突时的逻辑
        BinaryOperator<Integer> mergeFunction = (Integer preValue, Integer nextValue) -> {
            // 输出: preValue是: 18
            System.err.println("preValue是: " + preValue);
            // 输出: nextValue是: 100
            System.err.println("nextValue是: " + nextValue);
            return nextValue;
        };
    
        // Map容器提供者。 .collect(Collectors.toMap())返回的Map, 由此mapSupplier进行提供。
        Supplier<LinkedHashMap<String, Integer>> mapSupplier = LinkedHashMap::new;
    
        // 将Stream<T>转换为Map
        LinkedHashMap<String, Integer> resultMap = s.collect(
                Collectors.toMap(keyMapper, valueMapper, mergeFunction, mapSupplier)
        );
    
        // 输出: {张三=100, 李四=45, 王五=24}
        System.out.println(resultMap);
    }
    

Stream学习(下)之IntStream、LongStream、DoubleStream

声明 IntStream与LongStream与DoubleStream的用法几乎一模一样,且很多方法与Stream中一样,因此,下面以IntStream为例,只示例一些IntStream中有而Stream中没有的方法 或 示例一些常用的方法

  • asDoubleStream:将当前流转换为DoubleStream。

    示例:

    /*
     * --------------------------------------------- 示例 asDoubleStream()
     * 方法签名: DoubleStream asDoubleStream()
     * 方法说明: 将当前流转换为 DoubleStream
     */
    IntStream s1 = IntStream.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    DoubleStream doubleStream = s1.asDoubleStream();
    // 输出: 0.0    1.0       2.0       3.0       4.0       5.0       6.0       7.0       8.0       9.0
    doubleStream.forEachOrdered(x -> System.out.print(x + "\t\t"));
    
  • asLongStream:将当前流转换为LongStream。

    示例:

    /*
     * --------------------------------------------- 示例 asLongStream()
     * 方法签名: LongStream asLongStream()
     * 方法说明: 将当前流转换为 LongStream
     */
    IntStream s2 = IntStream.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    LongStream longStream = s2.asLongStream();
    // 换个行,便于观察
    System.out.println();
    // 输出: 0      1     2     3     4     5     6     7     8     9
    longStream.forEachOrdered(x -> System.out.print(x + "\t\t"));
    
  • average:求平均值。

    示例:

    /*
     * --------------------------------------------- 示例 average()
     * 方法签名: OptionalDouble average()
     * 方法说明: 求平均值
     */
    IntStream s3 = IntStream.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    OptionalDouble optionalDouble = s3.average();
    // 换个行,便于观察
    System.out.println();
    // 输出: 4.5
    optionalDouble.ifPresent(System.out::print);
    
  • boxed:将IntStream中的int转换为包装类Integer,得到Stream<Integer>。

    示例:

    /*
     * --------------------------------------------- 示例 boxed()
     * 方法签名: Stream<Integer> boxed()
     * 方法说明: 将IntStream中的int转换为包装类Integer,得到Stream<Integer>
     */
    IntStream s4 = IntStream.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    Stream<Integer> integerStream = s4.boxed();
    // 换个行,便于观察
    System.out.println();
    // 输出: 0      1     2     3     4     5     6     7     8     9
    integerStream.forEachOrdered(x -> System.out.print(x + "\t\t"));
    
  • range、rangeClosed:从给定范围内抽取元素形成流。

    示例:

    /*
     * --------------------------------------------- 示例 range()
     * 方法签名: static IntStream range(int startInclusive, int endExclusive)
     * 方法说明: 抽取给定范围(startInclusive到endExclusive)内的值,作为IntStream的元素。
     *          注:包含startInclusive, 不包含endExclusive。
     *          注:步径长度为1
     */
    IntStream rangeStream = IntStream.range(0, 6);
    // 换个行,便于观察
    System.out.println();
    // 输出: 0      1     2     3     4     5
    rangeStream.forEachOrdered(x -> System.out.print(x + "\t\t"));
    
    /*
     * --------------------------------------------- 示例 rangeClosed()
     * 方法签名: static IntStream rangeClosed(int startInclusive, int endInclusive)
     * 方法说明: 抽取给定范围(startInclusive到endInclusive)内的值,作为IntStream的元素。
     *          注:既包含startInclusive, 又包含endInclusive。
     *          注:步径长度为1
     */
    IntStream rangeClosedStream = IntStream.rangeClosed(0, 6);
    // 换个行,便于观察
    System.out.println();
    // 输出: 0      1     2     3     4     5     6
    rangeClosedStream.forEachOrdered(x -> System.out.print(x + "\t\t"));
    
  • sum:求和。

    示例:

    /*
     * --------------------------------------------- 示例 sum()
     * 方法签名: int sum()
     * 方法说明: 求和
     */
    IntStream s5 = IntStream.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    int sumValue = s5.sum();
    // 换个行,便于观察
    System.out.println();
    // 输出: 45
    System.out.println(sumValue);
    
  • toArray:将IntStream转换为数组。

    示例:

    /*
     * --------------------------------------------- 示例 toArray()
     * 方法签名: int[] toArray()
     * 方法说明: 将IntStream转换为数组
     */
    IntStream s6 = IntStream.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    int[] array = s6.toArray();
    // 换个行,便于观察
    System.out.println();
    // 输出: 45
    System.out.println(Arrays.toString(array));
    
  • summaryStatistics:根据IntStream获得统计对象, 通过该统计对象可以获得具体的统计信息(如:最大值、最小值、平均值、总和、数量)。

    示例:

    /*
     * --------------------------------------------- 示例 summaryStatistics()
     * 方法签名: IntSummaryStatistics summaryStatistics()
     * 方法说明: 根据IntStream获得统计对象, 通过该统计对象可以获得具
     *          体的统计信息(如:最大值、最小值、平均值、总和、数量)
     */
    IntStream s7 = IntStream.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    IntSummaryStatistics intSummaryStatistics = s7.summaryStatistics();
    // 换个行,便于观察
    System.out.println();
    // 输出: IntSummaryStatistics{count=10, sum=45, min=0, average=4.500000, max=9}
    System.out.println(intSummaryStatistics);
    

提示 Stream下半部分已学习完毕,Stream上半部分的学习可见《【jdk1.8特性】之Stream(上)》


^_^ 如有不当之处,欢迎指正

^_^ 参考资料
        《jdk api 1.8_google.CHM》

^_^ 测试代码托管链接
         https://github.com/JustryDeng…Jdk8Feature

^_^ 本文已经被收录进《程序员成长笔记》 ,笔者JustryDeng

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值