Java如何按相同ID合并两个对象列表生成含双方属性的新对象
Java Stream 合并同ID双列表对象实现方案
首先先修正你代码里的两个笔误,不然后面写逻辑会直接编译报错:
Item discount类名中间不能有空格,正确类名应为ItemDiscount- 两个类的ID字段命名大小写不一致:
Item里是全大写ID,ItemDiscount里是Id,调用对应getter的时候注意区分,不要写错方法名。
前置准备:定义返回的整合类
先定义你需要返回的ItemWithDiscount类,包含两个源类的全部字段,加全参构造方便Stream组装:
public class ItemWithDiscount { private Integer id; private String name; private Double price; private Double discount; // 全参构造,Stream组装时直接调用 public ItemWithDiscount(Integer id, String name, Double price, Double discount) { this.id = id; this.name = name; this.price = price; this.discount = discount; } // 这里省略getter/setter,实际项目必须补充,否则接口序列化时前端拿不到字段值 // 如果用Lombok,直接给类加@Data注解即可自动生成getter/setter、构造方法等 }
核心实现逻辑
不要在Stream里写嵌套循环匹配ID,数据量稍大性能会很差。正确思路是先把其中一个列表转成ID为key的Map,把查询复杂度降到O(1),再遍历另一个列表匹配组装:
import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; // 这里是你Service/Controller层的逻辑,假设已经从数据库/接口拿到两个源列表 List<Item> itemList = getSourceItemList(); List<ItemDiscount> discountList = getSourceDiscountList(); // 第一步:把折扣列表转成<商品ID, 折扣值>的映射Map Map<Integer, Double> discountIdMap = discountList.stream() .collect(Collectors.toMap( ItemDiscount::getId, // key是折扣对象的ID,对应类里的Id字段 ItemDiscount::getDiscount, // value是折扣值 // 重复key处理规则:如果同一个ID对应多条折扣记录,默认保留第一条,避免toMap抛出重复键异常 // 业务如果需要取最新折扣,改成 (oldVal, newVal) -> newVal 即可 (oldVal, newVal) -> oldVal )); // 第二步:遍历商品基础列表,匹配对应折扣,组装目标对象 List<ItemWithDiscount> resultList = itemList.stream() .map(item -> { // 按当前商品ID从Map里取折扣,没匹配到就返回null,也可以按业务设默认值1.0(代表无折扣) Double matchDiscount = discountIdMap.get(item.getID()); return new ItemWithDiscount( item.getID(), item.getName(), item.getPrice(), matchDiscount ); }) // 可选过滤规则:如果只需要返回有匹配折扣的商品,就加下面这行,不需要就删掉 .filter(vo -> vo.getDiscount() != null) .collect(Collectors.toList());
常见边界场景处理
- 如果你需要保留两个列表中所有出现过的ID(即某个ID只有折扣没有基础商品信息、或者只有基础信息没有折扣也需要返回),可以先把两个列表的所有ID收集成去重的Set,再分别从两个提前转好的属性Map里取对应值组装即可,绝大多数业务场景下以商品基础列表为主表匹配的逻辑就够用。
- 如果ID字段可能为null,记得在转Map和组装的时候加非空判断,避免空指针。
- 如果你的项目用的是Java 16+,也可以用
record来定义ItemWithDiscount,不用手写构造方法和getter,代码更简洁。
内容的提问来源于stack exchange,提问作者LDrof
相关产品推荐
相关产品推荐

