如何对比字段名不同的DriverPrimary与DriverSecondary两类POJO列表的差异
实现方案
前置准备
首先明确两个类的字段语义映射规则:
- 唯一标识匹配:
DriverPrimary.DriverId↔DriverSecondary.driverSecondaryDriverId - 属性值匹配:
DriverPrimary.role↔DriverSecondary.driverSecondaryDriverType
优先给两个POJO类添加私有字段对应的getter方法,若业务不允许修改原类,可通过反射工具读取字段值。
核心对比逻辑
采用「唯一键预映射」方案实现高效对比,时间复杂度为O(n+m),无需重写原类的equals、hashCode方法:
import java.util.*; import java.util.stream.Collectors; // 1. 将DriverSecondary列表转为<司机ID, 司机类型>的Map,用于快速匹配 Map<String, String> secondaryMap = driverSecondary.stream() .collect(Collectors.toMap( DriverSecondary::getDriverSecondaryDriverId, DriverSecondary::getDriverSecondaryDriverType, // 重复ID的冲突处理规则,可根据业务调整 (oldVal, newVal) -> oldVal )); // 2. 初始化三类差异结果的存储集合 List<DriverPrimary> onlyInPrimary = new ArrayList<>(); // 仅主列表存在 List<Map<String, Object>> updatedRecords = new ArrayList<>(); // 两边存在但属性不同 Set<String> matchedIds = new HashSet<>(); // 已匹配到的ID集合 // 3. 遍历主列表做匹配校验 for (DriverPrimary primary : driverPrimary) { String driverId = primary.getDriverId(); String primaryRole = primary.getRole(); if (secondaryMap.containsKey(driverId)) { matchedIds.add(driverId); String secondaryType = secondaryMap.get(driverId); // 对比属性值,支持空值判断 if (!Objects.equals(primaryRole, secondaryType)) { Map<String, Object> diff = new HashMap<>(); diff.put("driverId", driverId); diff.put("primaryRole", primaryRole); diff.put("secondaryType", secondaryType); updatedRecords.add(diff); } } else { onlyInPrimary.add(primary); } } // 4. 计算仅在副列表存在的记录 List<DriverSecondary> onlyInSecondary = driverSecondary.stream() .filter(item -> !matchedIds.contains(item.getDriverSecondaryDriverId())) .collect(Collectors.toList());
结果使用说明
onlyInPrimary:主列表存在、副列表不存在的记录,可用于新增同步逻辑onlyInSecondary:副列表存在、主列表不存在的记录,可用于删除/失效逻辑updatedRecords:两边都存在但属性值不一致的记录,可用于更新逻辑
如果需要自定义对比规则(比如忽略大小写、忽略首尾空格),仅需修改属性值对比的判断逻辑即可。
内容的提问来源于stack exchange,提问作者david
相关产品推荐
相关产品推荐

