排序和分组并在 Java 8 中找到每组的最大值

Sort and group by and find max of each group in Java 8

我有一个对象,它有一个名字和一个分数。我想按名称对元素进行排序并找到该名称的最高分数。

例如下面是对象 (name, score):

(a, 3)
(a, 9)
(b, 7)
(b, 10)
(c, 8)
(c, 3)

输出应该是:

(a, 9)
(b, 10)
(c, 8)

我可以使用下面的代码进行排序,但我无法找出 max

List<Record> result = list.stream()
        .sorted(Comparator.comparing(Record::score))
        .collect(Collectors.groupingBy(Record::name, LinkedHashMap::new, Collectors.toList()))
        .values().stream()
        .flatMap(Collection::stream)
        .collect(Collectors.toList());

您需要将 maxBy 链接到 groupinhBy 收集器:

Map<String,Record> result = 
    list.stream()
        .sorted(Comparator.comparing(Record::score))
        .collect(Collectors.groupingBy(Record::name, 
                                       LinkedHashMap::new,
                                       Collectors.maxBy(Comparator.comparing(Record::getScore))));

如果你只关心Record个实例,你可以获得那个Mapvalues()

@Eran 的回答很好。不过,我会反过来进行,首先分组然后减少:

List<Record> result = list.stream()
                              .collect(Collectors.groupingBy(Record::getName, 
                                      Collectors.maxBy(Comparator.comparing(Record::getScore))))
                              .values().stream()
                              .map(Optional::get)
                              .collect(Collectors.toList());

这里的一个缺点是你必须调用 optional#get。但是由于 groupingBy 产生的组永远不会为空,因此您可以调用 Optional#get 而不会出现异常。