Java List使用Stream排序和分组

时间:2018-07-11 13:52:10

标签: java list arraylist group-by

我有一个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"},

    ... 
]

2 个答案:

答案 0 :(得分:1)

使用Stream来收集值。您可以在Baeldung -- Guide to Java 8 groupingBy Collector

上找到示例
  

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 = Optional [POJO [A 10]],
  B = Optional [POJO [B 8]],
  C = Optional [POJO [C 4]],
  D = Optional [POJO [D 4]]}

答案 1 :(得分:1)

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

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

toMap方法的第三个参数(合并功能)始终选择较大的得分值。