Collectors.groupingBy() 分组、求和、统计、平均、最大(小)值

个人笔记,如有错请告知一下,谢谢。

pre:list数据 ENV:JDK8

tips:后面会根据情况变动数据。
//String name, Integer age, String score, Integer gender, BigDecimal height
ArrayList<Student> list = new ArrayList<>();
        list.add(new Student("王一", 21, "11", 1, new BigDecimal("193.0")));
        list.add(new Student("郑二", 22, "22", 0, new BigDecimal("171.0")));
        list.add(new Student("张三", 23, "33", 1, new BigDecimal("180.1")));
        list.add(new Student("李四", 24, "44", 0, new BigDecimal("183.2")));
        list.add(new Student("赵五", 25, "55", 1, new BigDecimal("178.3")));
        list.add(new Student("韩六", 26, "66", 0, new BigDecimal("169.4")));
        list.add(new Student("田七", 27, "77", 1, new BigDecimal("173.5")));
        list.add(new Student("卢八", 28, "88", 0, new BigDecimal("159.6")));
        list.add(new Student("钱九", 29, "99", 1, new BigDecimal("180.7")));
        list.add(new Student("魏十", null, null, null, null));
        list.add(new Student("肖十一", null, "", null, null));

分组

1 根据性别进行分组

1.1 为null的数据不需要,直接过滤

 Map<Integer, List<Student>> collect = list.stream()
                .filter(a -> a.getGender() != null)
                .collect(Collectors.groupingBy(Student::getGender));

1.2 需要保留为null的数据

 Map<? extends Serializable, List<Student>> collect1 = list.stream()
                .collect(Collectors.groupingBy(a -> {
                    if (a.getGender() == null) {
                        return "null";
                    }
                    return a.getGender();
                }));

1.3 结果

在这里插入图片描述

2 根据性别分组后,再根据分数分组,>=60:A <60:B ,为null的数据保留

Map<? extends Serializable, Map<String, List<Student>>> collect2 = list.stream().collect(Collectors.groupingBy(a -> {
            if (a.getGender() == null) {
                return "null";
            }
            return a.getGender();
        }, Collectors.groupingBy(b -> {
            String score = b.getScore();
            if (score == null) {
                return "B";
            } else {
                return score.compareTo("60") >= 0 ? "A" : "B";
            }
        })));

2.1 结果

在这里插入图片描述

3按照性别和身高分组,TreeMap默认按key升序 TreeMap的key不能为null

 TreeMap<String, List<Student>> collect3 = list.stream().collect(Collectors.groupingBy(a -> {
                    if (a.getGender() == null || a.getHeight() == null) {
                        return "null";
                    }
                    return a.getGender() + "->" + a.getHeight();
                }
                , TreeMap::new
                , Collectors.toList()));

3.1 结果

在这里插入图片描述

统计

1统计男女的个数

  Map<? extends Serializable, Long> collect4 = list.stream()
                .collect(Collectors.groupingBy(a -> {
                            if (a.getGender() == null) {
                                return "mix";
                            }
                            return a.getGender();
                        }
                        , Collectors.counting()));

1.1结果

在这里插入图片描述

2 按性别分组后,统计成绩60为分界的人数

Map<String, Map<String, Long>> collect5 = list.stream().collect(
                Collectors.groupingBy(//gender分组
                        a -> {
                            if (a.getGender() == null) {
                                return "null";//gender为null 
                            }
                            return a.getGender() == 1 ? "M" : "F";
                        }
                        , Collectors.groupingBy(//60为分界
                                b -> {
                                    String score = b.getScore();
                                    if (score == null) {
                                        return "null";
                                    } else {
                                        return score.compareTo("60") >= 0 ? "A" : "B";
                                    }
                                }
                                , Collectors.counting()//统计
                        )
                ));

2.1 结果

在这里插入图片描述

3 统计成绩60分界的男女各多少个

Map<String, Map<Integer, Long>> collect6 = list.stream()
                .filter(a -> StringUtils.isNoneBlank(a.getScore()))//过滤score为""和null的数据
                .filter(b -> b.getGender() != null)//过滤gender为null的数据
                .collect(
                        Collectors.groupingBy(
                                c -> c.getScore().compareTo("60") >= 0 ? "G" : "B",//以60分组
                                Collectors.groupingBy(
                                        Student::getGender,//以gender分组
                                        Collectors.counting()//统计
                                )
                        )
                );

3.1 结果

在这里插入图片描述

求和

1 统计男女各年龄之和

Map<Integer, Integer> collect7 = list.stream()
                .filter(a -> a.getAge()!=null || a.getGender() != null)
                .collect(Collectors.groupingBy(Student::getGender,
                        Collectors.summingInt(Student::getAge)));

1.1 结果

在这里插入图片描述

最大值

1 计算男、女中得最高分数的信息

Map<Integer, Student> collect9 = list.stream().filter(a -> a.getGender() != null)
                .collect(Collectors.groupingBy(
                        Student::getGender, Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparing(Student::getScore)), Optional::get)
                        )
                );

1.1 结果

在这里插入图片描述

1.2 问题

如上图结果可见,存在同一性别分数相同的人员信息,只返回了其中一条。
显然,有点不太对。

1.2.1 方法一、再添加一个条件

计算男女中最高的分数 分数相同去用时最短
注:对上面一种写法的精简

  Map<Integer, Student> collect11 = list.stream().filter(a -> a.getGender() != null)
                .collect(Collectors.toMap(
                        Student::getGender,//性别
                        Function.identity(),//t->t
                        BinaryOperator.maxBy(
                                Comparator.comparing(Student::getScore)//分数比较
                                        .thenComparing(b -> b.getEndTime().getTime() - b.getStartTime().getTime()//分数相同,按时间比较
                                                , Comparator.reverseOrder()))//外层用的max,故此处排序取反
                        )
                );

在这里插入图片描述

如果上面两个条件也相等呢。。。
1.2.2 将相同的存放在list中

暂时还没有好的处理措施,有好的方案请告知一下,谢谢

  1. 先按照年龄分组,以分数和用时为条件进行处理
  2. 遍历得到的Map,找到list中可能存在的分数和用时一样的数据
  3. 此处使用的是treemap。不写默认是HashMap
TreeMap<Integer, Student> collect12 = list.stream().filter(a -> a.getGender() != null)
                .collect(Collectors.toMap(
                        Student::getGender,
                        Function.identity(),
                        BinaryOperator.maxBy(
                                Comparator.comparing(Student::getScore)
                                        .thenComparing(b -> b.getEndTime().getTime() - b.getStartTime().getTime()
                                                , Comparator.reverseOrder())
                        ),
                        TreeMap::new
                        )
                );
HashMap<Integer, List<Student>> hashMap = new HashMap<>();
        collect12.forEach((k, v) -> {
            Map<Integer, ArrayList<Student>> listMap = list.stream()
                    .filter(a ->
                            k.equals(a.getGender())
                                    && v.getScore().equals(a.getScore())
                                    && (a.getEndTime().getTime()-a.getStartTime().getTime())
                                    	==(v.getEndTime().getTime() - v.getStartTime().getTime())
                    )
                    .collect(Collectors.toMap(
                            Student::getGender,
                            t -> {
                                List<Student> students = Collections.singletonList(t);
                                return new ArrayList<>(students);
                            },
                            (v1, v2) -> {
                                v2.addAll(v1);
                                return v2;
                            })
                    );
            hashMap.putAll(listMap);
        });

在这里插入图片描述

平均值

男女的分数平均值各多少

 Map<Integer, Double> collect13 = list.stream()
                .filter(a -> a.getGender() != null)
                .filter(b -> StringUtils.isNoneBlank(b.getScore()))
                .collect(Collectors.groupingBy(Student::getGender, 
                        Collectors.averagingDouble(a -> Double.parseDouble(a.getScore()))));

在这里插入图片描述

  • 10
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值