【问题标题】:Sort and group by and find max of each group in Java 8在 Java 8 中排序和分组并查找每个组的最大值
【发布时间】:2019-06-19 12:06:29
【问题描述】:

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

例如下面是对象(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());

【问题讨论】:

    标签: java sorting comparator


    【解决方案1】:

    @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 而不会出现异常。

    【讨论】:

      【解决方案2】:

      您需要将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()

      【讨论】:

      • 谢谢伊兰!!还有一个问题,如果我想将它存储为 Map 和 Map ...(我对 java 很陌生)
      • @Shraddha 最简单的方法是流过Map&lt;String,Record&gt; 的entrySet 并使用.collect(Collectors.toMap(Map.Entry::getKey,e-&gt;e.getValue().getScore()))。可能有一种方法可以在单个流管道中完成所有操作,但我现在想不出。
      • @Shraddha 也许你可以使用collectingAndThen。在我的回答中尝试管道,但使用.collect(Collectors.collectingAndThen(Collectors.groupingBy(...),Record::getScore)。我不确定语法,但类似的东西应该可以。
      • 是的,我已经试过了,但是它说的collectingAndThen方法在这里不适用。可能是我也使用了错误的语法。
      • @Shraddha 我想我把它锁在了错误的地方。尝试将Collectors.maxBy(Comparator.comparing(Record::getScore))(我的原始答案)替换为Collectors.collectingAndThen(Collectors.maxBy(...),Record::getScore)
      猜你喜欢
      • 2018-12-24
      • 1970-01-01
      • 1970-01-01
      • 2021-05-23
      • 2013-10-24
      • 1970-01-01
      • 2018-03-12
      • 1970-01-01
      • 2022-10-14
      相关资源
      最近更新 更多