JDK8+环境下合并列表中id与name相同的A类对象并聚合B列表
实现方案
推荐方案:Stream流分组合并(无需修改原类、无需反射)
直接用JDK自带的Stream分组能力实现,仅需几行代码就能满足需求,完全适配你无法修改A、B类的限制:
import org.junit.Test; import java.util.AbstractMap; import java.util.List; import java.util.stream.Collectors; public class MergeTest { @Test public void test() { List<A> originList = List.of( new A(1, "a1", List.of(new B(1, "1b"))), new A(1, "a1", List.of(new B(2, "2b"))), new A(2, "a2", List.of(new B(3, "3b"))) ); List<A> mergedList = originList.stream() // 以id+name作为分组键 .collect(Collectors.groupingBy(a -> new AbstractMap.SimpleEntry<>(a.id, a.name))) .values() .stream() .map(sameGroup -> { // 聚合同组所有B对象 List<B> mergedB = sameGroup.stream() .map(a -> a.listB) .flatMap(List::stream) .collect(Collectors.toList()); // 构造合并后的A对象 A first = sameGroup.get(0); return new A(first.id, first.name, mergedB); }) .collect(Collectors.toList()); } } // 原类定义无需任何修改 class A { public A(int id, String name, List<B> listB) { this.id = id; this.name = name; this.listB = listB; } int id; String name; List<B> listB; } class B { public B(int id, String name) { this.id = id; this.name = name; } int id; String name; }
反射不适合该场景的原因
完全没必要用反射,理由如下:
- 性能损耗:反射是运行时动态解析属性,性能远低于直接调用类的属性和构造方法
- 维护成本高:反射代码可读性差,且如果自动生成的A、B类后续修改了属性名,编译期不会报错,只会在运行时抛出异常,排查成本极高
- 需求匹配度低:当前场景分组键仅2个属性,合并逻辑简单,Stream实现的代码量比反射实现更少,更易维护
内容的提问来源于stack exchange,提问作者UnnameDSoS
相关产品推荐
相关产品推荐

