资讯专栏INFORMATION COLUMN

Java8中Collectors求和功能的自定义扩展

imtianx / 3153人阅读

摘要:起因业务中需要将一组数据分类后收集总和,原本可以使用,但是我们的数据源是类型的,而原生只提供了三种基础类型的方法。于是就自己动手丰衣足食吧。。期望目标实践依葫芦先分析一下方法该方法接受类型的参数,返回类型的实例化对象。

起因

业务中需要将一组数据分类后收集总和,原本可以使用Collectors.summingInt(),但是我们的数据源是BigDecimal类型的,而Java8原生只提供了summingInt、summingLong、summingDouble三种基础类型的方法。于是就自己动手丰衣足食吧。。

期望目标:

Map result = Arrays.stream(records).parallel().collect(Collectors.groupingBy(
    Record::getType, CollectorsUtil.summingBigDecimal(Record::getAmount)));
实践

1. 依葫芦
先分析一下Collectors.summingInt()方法

public static  Collector summingInt(ToIntFunction mapper) {
    return new CollectorImpl<>(
        () -> new int[1],
        (a, t) -> { a[0] += mapper.applyAsInt(t); },
        (a, b) -> { a[0] += b[0]; return a; },
        a -> a[0], CH_NOID);
    }

该方法接受ToIntFunction类型的参数,返回CollectorImpl类型的实例化对象。CollectorImplCollector接口的唯一实现类

CollectorImpl(Supplier supplier,
                BiConsumer accumulator,
                BinaryOperator combiner,
                Function finisher,
                Set characteristics) {
        this.supplier = supplier;
        this.accumulator = accumulator;
        this.combiner = combiner;
        this.finisher = finisher;
        this.characteristics = characteristics;
    }

分析CollectorImpl的构造器参数,可知summingInt()方法是这样的

arg[0]创建一个计算用的容器: () -> new int[1]
arg[1]为计算逻辑: (a, t) -> { a[0] += mapper.applyAsInt(t); }
arg[2]为合并逻辑: (a, b) -> { a[0] += b[0]; return a; }
arg[3]为返回最终计算值: a -> a[0]
arg[4]为空Set(不知道干什么用。。): Collections.emptySet()

2. 画瓢
很自然的,BigDecimal的就是这样了

public static  Collector summingBigDecimal(Function mapper) {
    return new CollectorImpl<>(() -> new BigDecimal[] { BigDecimal.ZERO }, (a, t) -> {
        a[0] = a[0].add(mapper.apply(t));
    }, (a, b) -> {
        a[0] = a[0].add(b[0]);
        return a;
    }, a -> a[0], CH_NOID);
}
Java8并行流的一些tips

千万注意共享变量的使用

注意装箱拆箱的开销

基于数据量考虑使用并行流本身的成本

谨慎在并行流中使用事务

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/68088.html

相关文章

  • Java8特性④Stream收集数据

    摘要:多级分组的为键,类型所对应的集合为值一级分类为的,二级分类为的按子集收集数据的为键,类型所对应的集合的为值分区分区是分组的特殊情况由一个谓词返回一个布尔值的函数作为分类函数,它称分区函数。 收集器可以简洁而灵活地定义collect用来生成结果集合的标准。更具体地说,对流调用 collect 方法将对流中的元素触发一个归约操作(由Collector来参数化)。一般来说,Collector...

    daryl 评论0 收藏0
  • Java8实战》-第六章读书笔记(用流收集数据-01)

    摘要:收集器用作高级归约刚刚的结论又引出了优秀的函数式设计的另一个好处更易复合和重用。更具体地说,对流调用方法将对流中的元素触发一个归约操作由来参数化。另一个常见的返回单个值的归约操作是对流中对象的一个数值字段求和。 用流收集数据 我们在前一章中学到,流可以用类似于数据库的操作帮助你处理集合。你可以把Java 8的流看作花哨又懒惰的数据集迭代器。它们支持两种类型的操作:中间操作(如 filt...

    EscapedDog 评论0 收藏0
  • Java8-Lambda表达式使用与Stream API

    摘要:前置数据提取对象中的一列提取列第一种写法简单一点的写法通过字段中条件过滤集合列表只要年纪大于岁的人列表中对象数值型列数据求和求和全部年纪取出集合符合条件的第一个元素取出年纪为岁的人简写对集合中对象 0x00. 前置数据 private List peoples = null; @BeforeEach void before () { peoples = new ArrayL...

    endless_road 评论0 收藏0
  • Java8流特性和Lambda表达式

    摘要:表达式体现了函数式编程的思想,即一个函数亦可以作为另一个函数参数和返回值,使用了函数作参数返回值的函数被称为高阶函数。对流对象进行及早求值,返回值不在是一个对象。 Java8主要的改变是为集合框架增加了流的概念,提高了集合的抽象层次。相比于旧有框架直接操作数据的内部处理方式,流+高阶函数的外部处理方式对数据封装更好。同时流的概念使得对并发编程支持更强。 在语法上Java8提供了Lamb...

    gaara 评论0 收藏0
  • Java8实用技能

    大概一年多之前,我对java8的理解还仅限一些只言片语的文章之上,后来出于对函数式编程的兴趣,买了本参考书看了一遍,然后放在了书架上,后来,当我接手大客户应用的开发工作之后,java8的一些工具,对我的效率有了不小的提升,因此想记录一下java8的一些常用场景,我希望这会成为一个小字典,能让我免于频繁翻书,但是总能找到自己想找的知识。 用于举例的model: @Data public class ...

    microcosm1994 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<