Java List使用Stream进行排序和分组



我有一个List<Records> =

[
{"studentId": "001", "date": "20180705", "courseId": "CS220", "score": "80"},
{"studentId": "001", "date": "20180702", "courseId": "CS320", "score": "75"},
{"studentId": "001", "date": "20180704", "courseId": "CS330", "score": "90"},
{"studentId": "002", "date": "20180703", "courseId": "CS640", "score": "95"},
{"studentId": "002", "date": "20180628", "courseId": "CS530", "score": "80"},
{"studentId": "002", "date": "20180701", "courseId": "CS545", "score": "90"},
{"studentId": "100", "date": "20180708", "courseId": "CS542", "score": "80"},
{"studentId": "100", "date": "20180629", "courseId": "CS240", "score": "97"},
... 
]

如何用相同的studentId对对象进行分组,并只保留列表中得分最高的对象?如下所示:List<Records> =

[
{"studentId": "001", "date": "20180704", "courseId": "CS330", "score": "90"},
{"studentId": "002", "date": "20180703", "courseId": "CS640", "score": "95"},
{"studentId": "100", "date": "20180629", "courseId": "CS240", "score": "97"},
... 
]

使用Stream收集值。您可以在Baeldung上找到一个示例--Java 8按收集器分组指南

2.8.从分组结果中获取最大值或最小值

这可以像一样使用

records.stream()
.collect(
Collectors.groupingBy(
Record::getStudentId, 
Collectors.maxBy(Compartor.comparingInt(Record::getPoint))
)
);

返回的映射将每个studentId作为一个键,并包含具有最大值的实例。使用POJO:的示例

class POJO {
String name;
int value;
//getters
//toString //POJO [%name% %value%]
}

快速测试:

Map<String, Optional<POJO>> map = Stream.of(
new POJO("A", 1), new POJO("A", 2), new POJO("A", 10),
new POJO("B", 8), new POJO("B", 4),
new POJO("C", 4),
new POJO("D", 4), new POJO("D", 1), new POJO("D", 2)
).collect(
Collectors.groupingBy(
POJO::getName, 
Collectors.maxBy(
Comparator.comparingInt(POJO::getValue)
)
)
);
System.out.println(map);

{A=可选[POJO[A10]],
B=可选[POJO[B8]],
C=可选[POHO[C4],
D=可选[POLO[D4]}

这可以通过java8的流来完成。

records.stream()
.collect(Collectors.toMap(Records::getStudentId ,Records::getScore,(s1,s2)->Math.max(s1,s2)))

toMap方法的第三个参数(合并函数(总是选择较大的分值。

最新更新