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

Java 11+优雅对比对象列表差异:基于value属性的实现

Java 11及以上版本中优雅对比对象列表差异的方案

需求说明

我们需要基于ColValueObject的value属性,找出两个对象列表的差异——也就是只在其中一个列表中出现的元素。示例场景:

  • 列表1:( { "left","one" }, { "left","two" } )
  • 列表2:( { "right","two" }, { "right","three" } )
    预期结果:( { "left","one" }, { "right","three" } )

传统嵌套循环实现冗余且效率偏低(时间复杂度O(n*m)),以下是几种更优雅的实现方案:


方案1:Stream+Set快速查找(高效简洁)

先提取两个列表的value到Set中(利用Set的O(1)查找特性),再通过Stream过滤出仅在单个列表存在的元素:

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class CompareListOfObjects {
    public static void main(String[] args) {
        List<ColValueObject> list1 = List.of(
                new ColValueObject("left", "Value one"),
                new ColValueObject("left", "Value two"),
                new ColValueObject("left", "Value three"));
        List<ColValueObject> list2 = List.of(
                new ColValueObject("right", "Value two"),
                new ColValueObject("right", "Value three"),
                new ColValueObject("right", "Value four"));

        List<ColValueObject> result = findDifferencesBetweenLists(list1, list2);
        result.forEach(System.out::println);
    }

    private static List<ColValueObject> findDifferencesBetweenLists(List<ColValueObject> list1, List<ColValueObject> list2) {
        // 提取两个列表的value集合,用于快速校验
        Set<String> list1Values = list1.stream()
                .map(ColValueObject::getValue)
                .collect(Collectors.toSet());
        Set<String> list2Values = list2.stream()
                .map(ColValueObject::getValue)
                .collect(Collectors.toSet());

        // 筛选出仅在单个列表中存在的元素
        List<ColValueObject> diff = new ArrayList<>();
        diff.addAll(list1.stream()
                .filter(obj -> !list2Values.contains(obj.getValue()))
                .collect(Collectors.toList()));
        diff.addAll(list2.stream()
                .filter(obj -> !list1Values.contains(obj.getValue()))
                .collect(Collectors.toList()));

        return diff;
    }
}

class ColValueObject {
    private String base;
    private String value;

    public ColValueObject(String base, String value) {
        this.base = base;
        this.value = value;
    }

    public String getBase() {
        return base;
    }

    public void setBase(String base) {
        this.base = base;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "ColValueObject{" +
                "base='" + base + '\'' +
                ", value='" + value + '\'' +
                '}';
    }
}

该方案时间复杂度优化为O(n+m),兼顾效率与可读性。


方案2:Collectors分组筛选(声明式风格)

通过合并列表并标记来源,按value分组后筛选出仅在单一来源出现的元素,更贴合函数式编程风格:

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

public class CompareListOfObjects {
    // main方法同方案1,此处省略

    private static List<ColValueObject> findDifferencesBetweenLists(List<ColValueObject> list1, List<ColValueObject> list2) {
        // 合并列表并标记元素来源
        List<SourceMarkedObject> merged = new ArrayList<>();
        merged.addAll(list1.stream().map(obj -> new SourceMarkedObject(obj, "list1")).collect(Collectors.toList()));
        merged.addAll(list2.stream().map(obj -> new SourceMarkedObject(obj, "list2")).collect(Collectors.toList()));

        // 按value分组,收集每个value对应的来源集合
        Map<String, Set<String>> valueSourceMap = merged.stream()
                .collect(Collectors.groupingBy(
                        item -> item.obj.getValue(),
                        Collectors.mapping(item -> item.source, Collectors.toSet())
                ));

        // 筛选出仅在单个列表出现的元素
        return merged.stream()
                .filter(item -> valueSourceMap.get(item.obj.getValue()).size() == 1)
                .map(item -> item.obj)
                .collect(Collectors.toList());
    }

    // 辅助类:标记元素所属列表
    static class SourceMarkedObject {
        ColValueObject obj;
        String source;

        public SourceMarkedObject(ColValueObject obj, String source) {
            this.obj = obj;
            this.source = source;
        }
    }
}

// ColValueObject类同方案1,此处省略

这种写法逻辑清晰,便于后续扩展复杂的对比规则。


方案3:借助Apache Commons Collections(简洁依赖版)

如果项目已引入Apache Commons Collections库,可直接利用工具类简化代码:

import org.apache.commons.collections4.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class CompareListOfObjects {
    // main方法同方案1,此处省略

    private static List<ColValueObject> findDifferencesBetweenLists(List<ColValueObject> list1, List<ColValueObject> list2) {
        // 提取两个列表的value列表
        List<String> list1Values = list1.stream().map(ColValueObject::getValue).collect(Collectors.toList());
        List<String> list2Values = list2.stream().map(ColValueObject::getValue).collect(Collectors.toList());

        // 利用工具类获取value的对称差集
        List<String> diffValues = new ArrayList<>(CollectionUtils.disjunction(list1Values, list2Values));

        // 从原列表中筛选对应元素
        List<ColValueObject> result = new ArrayList<>();
        result.addAll(list1.stream().filter(obj -> diffValues.contains(obj.getValue())).collect(Collectors.toList()));
        result.addAll(list2.stream().filter(obj -> diffValues.contains(obj.getValue())).collect(Collectors.toList()));

        return result;
    }
}

// ColValueObject类同方案1,此处省略

该方案代码最简洁,但需要引入第三方依赖:

<!-- Maven依赖示例 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.4</version>
</dependency>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 02:25:43