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
相关产品推荐
相关产品推荐

