Collectors.groupingBy() 分组、求和、统计、平均、最大(小)值
list数据tips:后面会根据情况变动数据。//String name, Integer age, String score, Integer gender, BigDecimal heightArrayList<Student> list = new ArrayList<>();list.add(new Student("王一", 21, "11", 1, new Bi
·
个人笔记,如有错请告知一下,谢谢。
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中
暂时还没有好的处理措施,有好的方案请告知一下,谢谢
- 先按照年龄分组,以分数和用时为条件进行处理
- 遍历得到的Map,找到list中可能存在的分数和用时一样的数据
- 此处使用的是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()))));
更多推荐
已为社区贡献1条内容
所有评论(0)