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

Java合并两个MyObject列表 按id去重保留isLatest非空元素

实现方案说明

注意你当前提供的实现修改了MyObject的相等判断逻辑,仅将id作为equals和hashCode的生成依据,违反了「原有equals()和hashCode()基于id、firstProp、secondProp三个字段生成、不可修改」的约束,会影响其他依赖原有相等逻辑的业务模块,不建议在生产环境使用。

推荐的最优实现方案

核心思路是用id作为键构建中间映射表,优先存储isLatest非空的元素,再补充不存在的isLatest为空的元素,时间复杂度为O(n+m)(n、m为两个列表的长度),完全不修改原有类的逻辑,符合所有约束:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class MergeListTest {
    public static void main(String[] args) {
        List<MyObject> listWithIsLatestSet = getListWithIsLatestSet();
        List<MyObject> listWithIsLatestNull = getListWithIsLatestNull();

        // 1. 构建id到对象的映射表,先存入所有isLatest非空的元素
        Map<Long, MyObject> idObjMap = new HashMap<>();
        listWithIsLatestSet.forEach(obj -> idObjMap.put(obj.getId(), obj));

        // 2. 遍历isLatest为空的列表,仅存入id不在映射表中的元素
        listWithIsLatestNull.forEach(obj -> {
            if (!idObjMap.containsKey(obj.getId())) {
                idObjMap.put(obj.getId(), obj);
            }
        });

        // 3. 按需转为List或Set
        List<MyObject> mergedList = new ArrayList<>(idObjMap.values());
        // 如果需要Set可以用:Set<MyObject> mergedSet = new HashSet<>(idObjMap.values());

        // 输出验证
        mergedList.forEach(System.out::println);
    }

    // 原有获取列表的方法,MyObject类使用业务原有定义,不修改任何注解
    private static List<MyObject> getListWithIsLatestSet() {
        // 构造逻辑和你的示例一致,此处省略实现
    }

    private static List<MyObject> getListWithIsLatestNull() {
        // 构造逻辑和你的示例一致,此处省略实现
    }
}

// 业务原有定义的MyObject,完全不做修改
class MyObject {
    private Long id;
    private String firstProp;
    private String secondProp;
    private Boolean isLatest;

    // 原有getter、setter、equals、hashCode方法保持不变
    public Long getId() {
        return id;
    }

    // 其他原有方法省略
}
方案优势
  • 完全符合业务约束:没有修改MyObject的任何原有逻辑,不会影响其他模块功能
  • 执行效率高:线性时间复杂度,远高于双重循环比对的O(n*m)方案
  • 逻辑清晰易维护:步骤拆分明确,后续调整去重或者优先级规则修改成本低
  • 灵活性高:最终结果可以自由选择转为List或者Set,适配不同业务场景

如果偏好Stream流式写法,也可以用Collectors.toMap实现等价逻辑,写法更简洁:

List<MyObject> mergedList = Stream.concat(listWithIsLatestSet.stream(), listWithIsLatestNull.stream())
        .collect(Collectors.toMap(
                MyObject::getId,
                obj -> obj,
                // 冲突时保留先出现的元素(非空列表在前,所以会自动保留非空元素)
                (oldVal, newVal) -> oldVal
        ))
        .values()
        .stream()
        .collect(Collectors.toList());

内容的提问来源于stack exchange,提问作者curious_brain

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 19:24:05