前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >reducing和reduce

reducing和reduce

作者头像
阿超
发布2022-08-21 14:31:53
9540
发布2022-08-21 14:31:53
举报
文章被收录于专栏:快乐阿超快乐阿超

java中,分为Collectors.reducingStream#reduce

reduce是减少的意思,此处意为聚合

聚合是聚拢、合并的意思

我们来看看这俩函数的区别吧,下方我用了静态导入:

代码语言:javascript
复制
import java.math.BigDecimal;
import java.util.*;
import java.util.function.BinaryOperator;
import java.util.stream.Collector;
import java.util.stream.Stream;

import static java.util.stream.Collectors.*;

首先是写法差异,对于只有一个参数的,这个参数指定了我们聚合的操作,此处我做一个累加,返回值为Optional证明有可能不存在值,就没有累加

代码语言:javascript
复制
Optional<Integer> sumOpt = Stream.iterate(0, i -> ++i).limit(10).collect(reducing(Integer::sum));
System.out.println(sumOpt);     // Optional[45]
sumOpt = Stream.iterate(0, i -> ++i).limit(10).reduce(Integer::sum);
System.out.println(sumOpt);     // Optional[45]

两个参数的,这里第一个参数为默认值,这里返回的是默认值+累加后的结果,此处默认值只能指定为相同类型

代码语言:javascript
复制
Integer sum = Stream.iterate(0, i -> ++i).limit(10).collect(reducing(10, Integer::sum));
System.out.println(sum);        // 55
sum = Stream.iterate(0, i -> ++i).limit(10).reduce(10, Integer::sum);
System.out.println(sum);        // 55

到此为止,其实都差不多,下面是三个参数的,这个三参用于聚合为其他类型的默认值,第一个参数还是默认值,第二个参数和第三个参数就有区别了

代码语言:javascript
复制
BigDecimal sumDecimal = Stream.iterate(0, i -> ++i).limit(10).collect(
        reducing(BigDecimal.ZERO, BigDecimal::new, BigDecimal::add));
System.out.println(sumDecimal); // 45
sumDecimal = Stream.iterate(0, i -> ++i).limit(10)
        .reduce(BigDecimal.ZERO, (d, i) -> d.add(new BigDecimal(i)), BigDecimal::add);
System.out.println(sumDecimal); // 45

可以看出我们的Collectors.reducing第二个参数是一个Function<Integer,BigDecimal>,入参为Integer返回值为BigDecimal,并没有进行聚合运算,而是进行了一个转换,此处是由Integer去生成一个BigDecimal,调用的java.math.BigDecimal#BigDecimal(int)这个构造,而第三个参数才是我们的累加操作

Stream#reduce中,第二个参数是一个BiFunction<BigDecimal, Integer, BigDecimal>,入参变为两个参数BigDecimal(已经累加的结果,并行流下值不可控)和Integer(本次参与运算的值),返回值为BigDecimal(运算结果),第三个参数是个BinaryOperator<BigDecimal>只在并行流场景下会用到,之前讲过,这里就不再表了,贴上链接:

reduce补充二

第三个参数区别:

也就是说,我们在串行流中哪怕将Stream#reduce的第三个参数,改为任意操作,他都是不影响结果执行的,例如我们这里取最大值

代码语言:javascript
复制
BigDecimal sumDecimal = Stream.iterate(0, i -> ++i).limit(10).collect(
                reducing(BigDecimal.ZERO, BigDecimal::new, BinaryOperator.maxBy(BigDecimal::compareTo)));
        System.out.println(sumDecimal); // 9
        sumDecimal = Stream.iterate(0, i -> ++i).limit(10)
                .reduce(BigDecimal.ZERO, (d, i) -> d.add(new BigDecimal(i)), BinaryOperator.maxBy(BigDecimal::compareTo));
        System.out.println(sumDecimal); // 45

可以看出,哪怕我们改为BinaryOperator.maxBy(BigDecimal::compareTo),是不影响Stream#reduce的,哪怕我们改为null

代码语言:javascript
复制
BigDecimal sumDecimal = Stream.iterate(0, i -> ++i).limit(10).collect(
        reducing(BigDecimal.ZERO, BigDecimal::new, (l, r) -> null));
System.out.println(sumDecimal); // null
sumDecimal = Stream.iterate(0, i -> ++i).limit(10)
        .reduce(BigDecimal.ZERO, (d, i) -> d.add(new BigDecimal(i)), (l, r) -> null);
System.out.println(sumDecimal); // 45

除非并行流场景下:

代码语言:javascript
复制
Optional<Integer> sumOpt = Stream.iterate(0, i -> ++i).parallel().limit(10).collect(reducing(Integer::sum));
System.out.println(sumOpt);     // Optional[45]
sumOpt = Stream.iterate(0, i -> ++i).parallel().limit(10).reduce(Integer::sum);
System.out.println(sumOpt);     // Optional[45]
Integer sum = Stream.iterate(0, i -> ++i).parallel().limit(10).collect(reducing(10, Integer::sum));
System.out.println(sum);        // 145
sum = Stream.iterate(0, i -> ++i).parallel().limit(10).reduce(10, Integer::sum);
System.out.println(sum);        // 145
BigDecimal sumDecimal = Stream.iterate(0, i -> ++i).parallel().limit(10).collect(
        reducing(BigDecimal.ZERO, BigDecimal::new, (l, r) -> null));
System.out.println(sumDecimal); // null
sumDecimal = Stream.iterate(0, i -> ++i).parallel().limit(10)
        .reduce(BigDecimal.ZERO, (d, i) -> d.add(new BigDecimal(i)), (l, r) -> null);
System.out.println(sumDecimal); // null

我们再次改为求最大值

代码语言:javascript
复制
BigDecimal sumDecimal = Stream.iterate(0, i -> ++i).parallel().limit(10).collect(
        reducing(BigDecimal.ZERO, BigDecimal::new, BinaryOperator.maxBy(BigDecimal::compareTo)));
System.out.println(sumDecimal); // 9
sumDecimal = Stream.iterate(0, i -> ++i).parallel().limit(10)
        .reduce(BigDecimal.ZERO, (d, i) -> d.add(new BigDecimal(i)), BinaryOperator.maxBy(BigDecimal::compareTo));
System.out.println(sumDecimal); // 9

可以看到并行流场景下均生效

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-07-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档