List集合分组,多列分组求sum、count、max、min,可支持基本数据类型以及BigDicimal数据类型,不用java8的label表达式

1 篇文章 0 订阅
1 篇文章 0 订阅

1、上代码之前我们先上源码,然后做一下分析:

default V merge(K key, V value,
            BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
        Objects.requireNonNull(remappingFunction);
        Objects.requireNonNull(value);
        V oldValue = get(key);
        V newValue = (oldValue == null) ? value :
                   remappingFunction.apply(oldValue, value);
        if(newValue == null) {
            remove(key);
        } else {
            put(key, newValue);
        }
        return newValue;
    }

通过对上面的源码分析,我想不管是初级程序猿还是老司机,大家都可以看懂,merge函数,就是每次拿Map里面key的oldValue和新传递的value进行函数运算,具体什么运算方式和传递的函数类型有关,如果你传递的是sum,那么就是oldValue和参数value相加,最后将sum结果put到当前Map对象中。分析到这里大家是不是就发现了新大陆。当然该函数也对你传递的value和funciton做了限制,就是非空,一旦为null就会抛出异常。

2、下面是实例代码

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * chen.kai
 * 测试 集合(list,set)中分组的sum,count
 */
public class Test {

    static class Persion {

        //姓名
        private String name;

        //年龄
        private Integer age;

        //身高
        private Double height;

        //财产
        private BigDecimal asset;

        public Persion (String name, Integer age, Double height) {
            this.name = name;
            this.age = age;
            this.height = height;
        }

        public Persion (String name, Integer age, Double height, BigDecimal asset) {
            this(name, age, height);
            this.asset = asset;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Integer getAge() {
            return age;
        }

        public void setAge(Integer age) {
            this.age = age;
        }

        public Double getHeight() {
            return height;
        }

        public void setHeight(Double height) {
            this.height = height;
        }

        public BigDecimal getAsset() {
            return asset;
        }

        public void setAsset(BigDecimal asset) {
            this.asset = asset;
        }
    }

    //分组聚合测试
    public static void main(String[] args) {
        List<Persion> list = new ArrayList<>();
        list.add(new Persion("张三", 20, 176.5));
        list.add(new Persion("李四", 25, 175.0, new BigDecimal(1000)));
        list.add(new Persion("王五", 25, 170.0, new BigDecimal("2000.53")));
        list.add(new Persion("丁六", 20, 176.5, new BigDecimal(2000)));
        list.add(new Persion("戊七", 30, 169.3, new BigDecimal("10000.99")));

        //求出每个年龄的所有资产,从肉眼看有三条数据,那我们测试一下,看是否处理正确,其中张三的asset = null,这是一个很敏感的数据
        Map<Integer, BigDecimal> map1 = new HashMap<>();
        for (Persion p : list) {
            map1.merge(p.getAge(), p.getAsset(), BigDecimal::add);
        }
        System.out.println(map1.toString());
    }

运行结果如下:

动动你们的小脑筋,为什么会报错呢?我们上面分析源码是不是说过,该函数对传递的参数有一定的限制,就是value和function必须非空,但是张三数据的asset=null,ok,找到了问题,那么我们改变写法,写一个三目表达式,解决问题,

 //分组聚合测试
    public static void main(String[] args) {
        List<Persion> list = new ArrayList<>();
        list.add(new Persion("张三", 20, 176.5));
        list.add(new Persion("李四", 25, 175.0, new BigDecimal(1000)));
        list.add(new Persion("王五", 25, 170.0, new BigDecimal("2000.53")));
        list.add(new Persion("丁六", 20, 176.5, new BigDecimal(2000)));
        list.add(new Persion("戊七", 30, 169.3, new BigDecimal("10000.99")));

        //求出每个年龄的所有资产,从肉眼看有三条数据,那我们测试一下,看是否处理正确,其中张三的asset = null,这是一个很敏感的数据
        Map<Integer, BigDecimal> map1 = new HashMap<>();
        for (Persion p : list) {
            map1.merge(p.getAge(), p.getAsset() == null ? BigDecimal.ZERO : p.getAsset(), BigDecimal::add);
        }
        System.out.println(map1.toString());
    }

运行结果如下,答案完全正确,完美解决:

3、多列分组,sum测试:

 //分组聚合测试
    public static void main(String[] args) {
        List<Persion> list = new ArrayList<>();
        list.add(new Persion("张三", 20, 176.5));
        list.add(new Persion("李四", 25, 175.0, new BigDecimal(1000)));
        list.add(new Persion("王五", 25, 170.0, new BigDecimal("2000.53")));
        list.add(new Persion("丁六", 20, 176.5, new BigDecimal(2000)));
        list.add(new Persion("戊七", 30, 169.3, new BigDecimal("10000.99")));
        list.add(new Persion("李一", 30, 169.3, new BigDecimal("20000.11")));
        //求出每个年龄段,每个身高的资产情况

        Map<String, BigDecimal> map = new HashMap<>();
        for (Persion p : list) {
            map.merge(p.getAge() + "_" + p.getHeight(), p.getAsset() == null ? BigDecimal.ZERO : p.getAsset(), BigDecimal::add);
        }
        System.out.println(map.toString());
    }

4、count,max测试

//分组聚合测试
    public static void main(String[] args) {
        List<Persion> list = new ArrayList<>();
        list.add(new Persion("张三", 20, 176.5));
        list.add(new Persion("李四", 25, 175.0, new BigDecimal(1000)));
        list.add(new Persion("王五", 25, 170.0, new BigDecimal("2000.53")));
        list.add(new Persion("丁六", 20, 176.5, new BigDecimal(2000)));
        list.add(new Persion("戊七", 30, 169.3, new BigDecimal("10000.99")));
        list.add(new Persion("李一", 30, 169.3, new BigDecimal("20000.11")));

        //count合计,求出每个年龄段有多少人
        Map<Integer, Integer> map3 = new HashMap<>();
        for (Persion p: list) {
            map3.merge(p.getAge(), 1, Integer::sum);
        }
        System.out.println("count合计:" + map3.toString());

        //max,求出每个年龄段最大身高
        Map<Integer, Double> map4 = new HashMap<>();
        for (Persion p: list) {
            map4.merge(p.getAge(), p.getHeight(), Double::max);
        }
        System.out.println("求max:" +map4.toString());
    }

运行结果安全无误:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值