You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 8如何按名称排序并分组获取每组最高得分?

解决Record对象按name分组并取每组最高score的问题

嘿,我来帮你搞定这个需求!你现在的代码其实只是完成了排序+分组+展平的操作,并没有真正筛选出每个name对应的最高score的Record——最后得到的还是所有元素,只是按score排序后按name归了类,这显然不是你要的结果。

下面给你两种简洁高效的实现方式:

方法一:使用groupingBy + maxBy

直接在分组阶段就收集每组的最大值,不需要先排序再处理:

List<Record> result = list.stream()
    .collect(Collectors.groupingBy(
        Record::name,
        LinkedHashMap::new, // 保留原列表中name的出现顺序
        Collectors.maxBy(Comparator.comparingInt(Record::score))
    ))
    .values()
    .stream()
    .filter(Optional::isPresent) // 处理空分组的边界情况(你的示例里不会出现)
    .map(Optional::get)
    .collect(Collectors.toList());

代码说明:

  • groupingBy的第三个参数是下游收集器,用maxBy指定按score比较,直接拿到每组中score最大的Record;
  • maxBy会返回Optional<Record>(防止分组为空的情况),所以需要用filter和map取出实际的Record对象;
  • LinkedHashMap用来保证结果的顺序和原列表中name首次出现的顺序一致。

方法二:使用toMap合并重复项

这种方式更简洁,直接通过Map的合并规则保留最大值:

List<Record> result = new ArrayList<>(list.stream()
    .collect(Collectors.toMap(
        Record::name,
        Function.identity(), // 直接把Record作为value
        // 合并规则:当key重复时,保留score更大的那个Record
        (existingRecord, newRecord) -> existingRecord.score() > newRecord.score() ? existingRecord : newRecord,
        LinkedHashMap::new // 保持顺序
    ))
    .values());

代码说明:

  • toMap的第三个参数是合并函数,遇到同一个name的Record时,我们比较两者的score,留下更大的那个;
  • 最后把Map的values转成ArrayList,就得到了每个name对应最高score的Record列表。

这两种方法都能直接得到你想要的结果:(a, 9) (b, 10) (c, 8),而且比你原来的代码更高效——不需要先排序整个列表,分组时就完成了最大值的筛选。

内容的提问来源于stack exchange,提问作者Shraddha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:20:35