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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 23:18:47