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

Java 8如何用函数式方法实现对象列表分组后取Top N的需求?

实现方案

注意:你提供的Data类构造方法存在赋值方向错误的问题,会导致所有属性无法正确初始化,需要先修正:

public Data(double score, String name, String group) {
    this.score = score;
    this.name = name;
    this.group = group;
}

使用Java 8 Stream API可以非常简洁的完成需求,不需要提前显式构建Map<String, List<Data>>,完整逻辑可以在一条Stream流中完成:

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public List<Data> getTopNGroupMax(List<Data> dataList, int topN) {
    return dataList.stream()
            // 按group分组,每个组直接取score最高的1条数据
            .collect(Collectors.groupingBy(
                    Data::getGroup,
                    Collectors.collectingAndThen(
                            Collectors.maxBy(Comparator.comparingDouble(Data::getScore)),
                            opt -> opt.orElse(null)
                    )
            ))
            .values().stream()
            // 过滤极端场景下的空值
            .filter(data -> data != null)
            // 所有组的最高分按score降序排序
            .sorted(Comparator.comparingDouble(Data::getScore).reversed())
            // 取前N条结果
            .limit(topN)
            .collect(Collectors.toList());
}

测试调用

public static void main(String args[]) {
    ArrayList<Data> dataList = new ArrayList<Data>();
    dataList.add(new Data(1.0, "one", "A"));
    dataList.add(new Data(4.0, "two", "A"));
    dataList.add(new Data(3.0, "three", "B"));
    dataList.add(new Data(2.0, "four", "C"));
    dataList.add(new Data(7.0, "five", "D"));
    dataList.add(new Data(17.0, "five", "D"));

    ArrayList<Data> dataList2 = new ArrayList<Data>();
    dataList2.add(new Data(3.0, "one", "A"));
    dataList2.add(new Data(5.0, "six", "A"));
    dataList2.add(new Data(3.14, "two", "B"));
    dataList2.add(new Data(3.14, "three", "C"));

    MyClass handler = new MyClass();
    // 取全局Top3
    List<Data> result1 = handler.getTopNGroupMax(dataList, 3);
    List<Data> result2 = handler.getTopNGroupMax(dataList2, 3);
    
    // 输出和你提供的预期完全一致
    result1.forEach(data -> System.out.printf("Data(%.1f, %s, %s)%n", data.getScore(), data.getName(), data.getGroup()));
    System.out.println("---");
    result2.forEach(data -> System.out.printf("Data(%.2f, %s, %s)%n", data.getScore(), data.getName(), data.getGroup()));
}

如果确实需要先存储Map<String, List<Data>>结构做后续复用,也可以单独拆分逻辑:

// 第一步:构建分组Map,每个组内的List按score降序排序
Map<String, List<Data>> groupMap = dataList.stream()
        .collect(Collectors.groupingBy(
                Data::getGroup,
                Collectors.collectingAndThen(
                        Collectors.toList(),
                        list -> list.stream()
                                .sorted(Comparator.comparingDouble(Data::getScore).reversed())
                                .collect(Collectors.toList())
                )
        ));

// 第二步:取TopN结果
List<Data> result = groupMap.values().stream()
        .filter(list -> !list.isEmpty())
        .map(list -> list.get(0))
        .sorted(Comparator.comparingDouble(Data::getScore).reversed())
        .limit(3)
        .collect(Collectors.toList());

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 07:42:03