对数据分组处理的常用处理方式
数据准备
List<Result> list = new ArrayList<>();
list.add(new Result("张三", "语文", 93, 1));
list.add(new Result("李四", "语文", 88, 0));
list.add(new Result("王五", "语文", 75, 1));
list.add(new Result("韩六", "语文", 66, 0));
list.add(new Result("张三", "数学", 63, 1));
list.add(new Result("李四", "数学", 74, 0));
list.add(new Result("王五", "数学", 85, 1));
list.add(new Result("韩六", "数学", 96, 0));
list.add(new Result("张三", "英语", 88, 1));
list.add(new Result("李四", "英语", 88, 0));
list.add(new Result("王五", "英语", 88, 1));
list.add(new Result("韩六", "英语", 88, 0));
需求描述:
按照性别分组后找到每科成绩最高的数据
代码实现
使用Collectors.groupingBy处理
Map<Integer, Map<String, Optional<Result>>> collect = list.stream().collect(
Collectors.groupingBy(Result::getGender
, Collectors.groupingBy(Result::getSubject
, Collectors.maxBy(Comparator.comparing(Result::getScore)))));
结果
针对上面写法的修改
使用Collectors.collectingAndThen处理Optional问题
Map<Integer, Map<String, Result>> collect1 = list.stream().collect(
Collectors.groupingBy(Result::getGender
, Collectors.groupingBy(Result::getSubject
, Collectors.collectingAndThen(Collectors.maxBy(
Comparator.comparing(Result::getScore)), Optional::get))));
结果
替换写法
使用toMap替换第二个groupingby
Map<Integer, Map<String, Result>> map1 = list.stream().collect(
Collectors.groupingBy(Result::getGender
, Collectors.toMap(Result::getSubject
, Function.identity()
, BinaryOperator.maxBy(Comparator.comparing(Result::getScore)))));
要注意toMap第三个参数的类型是BinaryOperator mergeFunction,故使用的是BinaryOperator.maxBy()而非Collectors.maxBy()
如果想只要结果中一个字段如:名字
Map<Integer, Map<String, String>> collect2 = list.stream().collect(
Collectors.groupingBy(Result::getGender
, Collectors.groupingBy(Result::getSubject
, Collectors.collectingAndThen(
Collectors.maxBy(
Comparator.comparing(Result::getScore))
, a -> a.get().getName()
)
)
)
);
注意
使用Lambda时,请及时处理数据为null的情况。