如何通过Stream API按ID分组并合并Test对象
按ID分组并合并Test对象的Stream API实现
定义与实例化
我定义了如下Test类(补充必要的构造方法、getter/setter以支持Stream操作):
public class Test { private Integer id; private String first; private String second; public Test(Integer id, String first, String second) { this.id = id; this.first = first; this.second = second; } // Getter和Setter方法 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getFirst() { return first; } public void setFirst(String first) { this.first = first; } public String getSecond() { return second; } public void setSecond(String second) { this.second = second; } }
并实例化了多个对象:
Test test1 = new Test(1, "qweqwe", null); Test test2 = new Test(2, "qweqwe", null); Test test3 = new Test(3, "qweqwe", null); Test test4 = new Test(1, null, "dfdsfg"); Test test5 = new Test(2, null, "dfdsfg"); Test test6 = new Test(3, null, "dfdsfg");
需求
通过Stream API按id对这些对象分组并合并,最终得到每个id对应一个完整字段的List<Test>,结果如下:
(1, "qweqwe", "dfdsfg")(2, "qweqwe", "dfdsfg")(3, "qweqwe", "dfdsfg")
当前仅能通过collect(Collectors.groupingBy(Test::getId, Collectors.toList()))得到Map<Integer, List<Test>>,不符合需求。
实现方法
方法一:分组后直接合并(groupingBy + reducing)
利用Collectors.reducing在分组时直接完成对象合并,再提取结果转为List:
import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; List<Test> mergedList = Arrays.asList(test1, test2, test3, test4, test5, test6) .stream() .collect(Collectors.groupingBy( Test::getId, Collectors.reducing( new Test(null, null, null), // 初始化空对象 (testA, testB) -> { // 合并逻辑:优先保留非null的字段值 Test merged = new Test(testA.getId(), null, null); merged.setFirst(testA.getFirst() != null ? testA.getFirst() : testB.getFirst()); merged.setSecond(testA.getSecond() != null ? testA.getSecond() : testB.getSecond()); return merged; } ) )) .values() // 获取所有合并后的Test对象 .stream() .collect(Collectors.toList());
方法二:先分组再遍历合并
先按id分组得到Map,再遍历每个分组的对象列表,提取非null字段合并为新对象:
import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; List<Test> mergedList = Arrays.asList(test1, test2, test3, test4, test5, test6) .stream() .collect(Collectors.groupingBy(Test::getId)) .entrySet() .stream() .map(entry -> { Integer id = entry.getKey(); List<Test> testGroup = entry.getValue(); // 提取分组内非null的first字段 String first = testGroup.stream() .map(Test::getFirst) .filter(Objects::nonNull) .findFirst() .orElse(null); // 提取分组内非null的second字段 String second = testGroup.stream() .map(Test::getSecond) .filter(Objects::nonNull) .findFirst() .orElse(null); return new Test(id, first, second); }) .collect(Collectors.toList());
说明
两种方法的核心逻辑一致:先按id分组,再对每组内的Test对象进行字段合并,优先保留非null的字段值。需确保Test类具备对应的构造方法、getter和setter,否则无法正常操作字段。
内容的提问来源于stack exchange,提问作者hvrhand
相关产品推荐
相关产品推荐

