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

Java Stream按对象分组:将Data列表按name聚合options

用Java Stream实现按Name分组合并Option的解决方案

嘿,这个需求很常见,用Java Stream的收集器就能轻松搞定。先给你理清楚思路,再上代码,保证能得到你想要的结构。

首先得完善下你的Data类——原代码里没有name、option和options的getter,Stream里访问不了私有字段;而且构造函数里最好把传入的option直接加到options列表里,这样合并的时候更顺畅:

class Data {
    private String name;
    private String option;
    private List<String> options = new ArrayList<>();

    public Data(String name, String option) {
        this.name = name;
        this.option = option;
        // 初始化时就把当前option加入options列表
        this.options.add(option);
    }

    // 补充必要的getter方法
    public String getName() {
        return name;
    }

    public String getOption() {
        return option;
    }

    public List<String> getOptions() {
        return options;
    }

    public void addOption(String option) {
        options.add(option);
    }
}

接下来就是核心的Stream分组代码,我推荐用Collectors.toMap来实现,逻辑更直观:

List<Data> data = new ArrayList<>();
data.add(new Data("d1", "option1"));
data.add(new Data("d2", "option1"));
data.add(new Data("d1", "option2"));
data.add(new Data("d3", "option1"));
data.add(new Data("d3", "option2"));
data.add(new Data("d3", "option3"));

// 分组合并逻辑
Map<String, Data> groupedResult = data.stream()
    .collect(Collectors.toMap(
        // 分组的key:提取Data的name
        Data::getName,
        // 每个元素生成对应的value:新建一个Data对象(避免修改原列表的对象)
        d -> new Data(d.getName(), d.getOption()),
        // 合并规则:当同一个name出现多次时,把新Data的option合并到已有Data的options里
        (existingData, newData) -> {
            existingData.getOptions().addAll(newData.getOptions());
            return existingData;
        }
    ));

代码解释

  1. Collectors.toMap的三个参数:

    • 第一个参数Data::getName:指定用name作为Map的key;
    • 第二个参数:把每个原始的Data对象转换成一个新的Data(这样不会修改原列表里的对象,是更安全的做法);
    • 第三个参数:当同一个key(name)重复时,将新对象的options合并到已有的对象中,最终每个key对应一个包含所有option的Data。
  2. 验证结果:如果要输出成你给的JSON格式,只需要遍历Map打印就行:

// 打印结果(模拟JSON格式)
groupedResult.forEach((key, value) -> {
    System.out.println("\"" + key + "\": {");
    System.out.println("  \"name\": \"" + value.getName() + "\",");
    System.out.println("  \"options\": " + value.getOptions());
    System.out.println("}");
});

输出结果完全符合你的要求:

"d1": {
  "name": "d1",
  "options": [option1, option2]
}
"d2": {
  "name": "d2",
  "options": [option1]
}
"d3": {
  "name": "d3",
  "options": [option1, option2, option3]
}

另外,如果你不想新建Data对象,也可以用Collectors.groupingBy配合Collectors.reducing来直接合并原对象,但这样会修改原列表里的Data实例,需要根据你的业务场景选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:08:07