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

Java中如何获取新旧员工对象ArrayList的差异?

对比员工新旧列表差异:基于ObjectDifferBuilder的实现方案

我之前也遇到过类似的对象列表差异对比需求,用你提到的这个工具确实能很好解决。针对你的员工对象场景(包含唯一标识id、name、age、grp属性),我整理了一套完整的实现步骤,帮你精准提取新增、删除和属性变更的差异:

1. 先定义员工实体类

核心要确保基于id重写equals和hashCode,这是工具能正确匹配新旧列表中同一个员工的关键:

import java.util.Objects;

public class Employee {
    private String id; // 唯一标识,用于匹配新旧对象
    private String name;
    private int age;
    private String grp;

    // 构造器
    public Employee(String id, String name, int age, String grp) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.grp = grp;
    }

    // Getter和Setter方法
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    public String getGrp() { return grp; }
    public void setGrp(String grp) { this.grp = grp; }

    // 基于id实现equals和hashCode
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Employee employee = (Employee) o;
        return Objects.equals(id, employee.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}

2. 构建差异对比器并解析差异

结合你提到的actionDataList,下面是完整的对比和差异收集代码:

import de.danielbechler.diff.ObjectDiffer;
import de.danielbechler.diff.ObjectDifferBuilder;
import de.danielbechler.diff.node.DiffNode;
import de.danielbechler.diff.node.Visit;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class EmployeeDiffHandler {
    public static void main(String[] args) {
        // 模拟旧员工列表
        List<Employee> oldEmployeeList = new ArrayList<>();
        oldEmployeeList.add(new Employee("EMP001", "张三", 30, "技术部"));
        oldEmployeeList.add(new Employee("EMP002", "李四", 28, "市场部"));

        // 模拟修改后的新员工列表:新增EMP003,修改EMP001的年龄和部门,删除EMP002
        List<Employee> newEmployeeList = new ArrayList<>();
        newEmployeeList.add(new Employee("EMP001", "张三", 31, "研发部"));
        newEmployeeList.add(new Employee("EMP003", "王五", 25, "人事部"));

        // 构建自定义规则的差异对比器:以id识别同一个员工
        ObjectDiffer differ = ObjectDifferBuilder.startBuilding()
                .comparison()
                    .ofType(List.class)
                    .identifyObjectsBy((obj1, obj2) -> {
                        if (obj1 instanceof Employee && obj2 instanceof Employee) {
                            return ((Employee) obj1).getId().equals(((Employee) obj2).getId());
                        }
                        return obj1.equals(obj2);
                    })
                .build();

        // 执行新旧列表对比
        DiffNode diffNode = differ.compare(newEmployeeList, oldEmployeeList);

        // 收集差异到actionDataList,用于后续打印或存储
        List<String> actionDataList = new ArrayList<>();
        diffNode.visit((node, visit) -> {
            if (node.hasChanges()) {
                Object oldValue = node.canonicalGet(oldEmployeeList);
                Object newValue = node.canonicalGet(newEmployeeList);

                // 区分差异类型:新增、删除、属性修改
                if (node.isAdded()) {
                    Employee addedEmp = (Employee) newValue;
                    actionDataList.add(String.format("【新增员工】ID:%s,姓名:%s,年龄:%d,部门:%s",
                            addedEmp.getId(), addedEmp.getName(), addedEmp.getAge(), addedEmp.getGrp()));
                } else if (node.isRemoved()) {
                    Employee removedEmp = (Employee) oldValue;
                    actionDataList.add(String.format("【删除员工】ID:%s,姓名:%s",
                            removedEmp.getId(), removedEmp.getName()));
                } else if (node.isChanged()) {
                    // 通过路径解析找到对应的员工
                    String path = node.getPath();
                    String empId = path.substring(path.indexOf('[') + 1, path.indexOf(']'));
                    Optional<Employee> targetEmp = newEmployeeList.stream()
                            .filter(emp -> emp.getId().equals(empId))
                            .findFirst();
                    if (targetEmp.isPresent()) {
                        String propName = path.substring(path.lastIndexOf('.') + 1);
                        actionDataList.add(String.format("【修改员工属性】员工:%s(ID:%s),属性:%s,旧值:%s,新值:%s",
                                targetEmp.get().getName(), empId, propName, oldValue, newValue));
                    }
                }
            }
        });

        // 打印差异结果
        System.out.println("员工列表差异详情:");
        actionDataList.forEach(System.out::println);
    }
}

3. 关键注意事项

  • 对象匹配规则:必须配置基于id的识别逻辑,否则工具会默认用对象引用判断,导致无法匹配同一个员工的属性变更。
  • 差异类型判断:DiffNode提供的isAdded()、isRemoved()、isChanged()方法,可以精准区分列表的三类变更。
  • 路径解析:node.getPath()返回的路径格式(如[0].age),可以帮你定位到具体的员工和修改的属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:51:36