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; } ));
代码解释
Collectors.toMap的三个参数:- 第一个参数
Data::getName:指定用name作为Map的key; - 第二个参数:把每个原始的
Data对象转换成一个新的Data(这样不会修改原列表里的对象,是更安全的做法); - 第三个参数:当同一个key(name)重复时,将新对象的
options合并到已有的对象中,最终每个key对应一个包含所有option的Data。
- 第一个参数
验证结果:如果要输出成你给的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
相关产品推荐
相关产品推荐

