首先看一下我的文件结构
1.EnumType 类
public enum EnumType {ADD("ADD"),MODIFIED("MODIFIED"), DELETED("DELETED");//创建私有变量private String type;EnumType(String type) {this.type = type;}
}
2.OperationType类
public class OperationType {private static final EnumType ADD=EnumType.ADD;private static final EnumType MODIFIED=EnumType.MODIFIED;private static final EnumType REMOVED=EnumType.DELETED;
}
3.DiffListUtil类
public class DiffListUtil {@Datapublic static class TargetWrapper<T> {private T target;private EnumType type;public TargetWrapper(T target, EnumType type) {this.target = target;this.type = type;}// Getters and setters for target and type}@Data@Accessors(chain = true)public static class DiffResult<T> {private List<TargetWrapper<T>> allList;/*** 新增对象列表*/private List<TargetWrapper<T>> addedList;/*** 修改后的对象列表*/private List<TargetWrapper<T>> changedList;/*** 已删除对象列表*/private List<TargetWrapper<T>> deletedList;}/*** 对比两个List的元素* <p>* 如果 baseList 的元素在 targetList 中存在 PrimaryKey 相等的元素并且 elementComparator 比较结果不相等,则将修改后的值添加到changedList列表中;* 如果 baseList 的元素在 targetList 中不存在,将baseList中的元素添加到deletedList中;* 如果 targetList 的元素在 baseList 中不存在,将targetList中的元素添加到addedList中;* <p>* complexity: O(n)** @param baseList 基础List(原来的List)* @param targetList 目标List(最新的List)* @param elementComparator 元素比较器*primaryKeyExtractor* @param <T>* @return 对比结果*/public static <T> DiffResult<T> diffList(List<T> baseList,List<T> targetList,@NotNull Function<T, Object> primaryKeyExtractor,@NotNull Comparator<T> elementComparator) {DiffResult<T> checkResult = checkEmptyAndReturn(baseList, targetList);if (checkResult != null) {return checkResult;}Map<Object,T> baseMap = new HashMap<>(4096);for(T base : baseList){Object key = primaryKeyExtractor.apply(base);baseMap.put(key,base);}List<TargetWrapper<T>> addedList = new ArrayList<>();List<TargetWrapper<T>> changedList = new ArrayList<>();List<TargetWrapper<T>> deletedList = new ArrayList<>();List<TargetWrapper<T>> allList = new ArrayList<>();//找出新增的 和需要更新的for (T target : targetList) {Object key = primaryKeyExtractor.apply(target);T base = baseMap.get(key);if(base == null){addedList.add(new TargetWrapper<T>(target, EnumType.ADD));}else{baseMap.remove(key);if (elementComparator.compare(base, target) != 0) {changedList.add(new TargetWrapper<T>(target, EnumType.MODIFIED));}}}//剩余的就是需要删除的Set<Map.Entry<Object, T>> entrySet = baseMap.entrySet();if(CollUtil.isNotEmpty(entrySet)){for(Map.Entry<Object, T> entry:entrySet){deletedList.add(new TargetWrapper<T>(entry.getValue(), EnumType.DELETED));}}allList.addAll(addedList);addedList.addAll(changedList);addedList.addAll(deletedList);return new DiffResult<T>().setAddedList(addedList).setChangedList(changedList).setDeletedList(deletedList).setAllList(allList);}private static <T, V> void setFieldValue(T object, Function<? super T,V> fieldGetter, String value) {try {Field field = fieldGetter.getClass().getDeclaredField("value");field.setAccessible(true);field.set(fieldGetter.apply(object), value);} catch (NoSuchFieldException | IllegalAccessException e) {e.printStackTrace();}}/*** 检查baseList 和 targetList 为empty(null||size==0)的情况** @param baseList* @param targetList* @param <T>* @return*/private static <T> DiffResult<T> checkEmptyAndReturn(List<T> baseList, List<T> targetList) {if (CollUtil.isEmpty(baseList) && CollUtil.isEmpty(targetList)) {return new DiffResult<T>().setAddedList(null).setChangedList(null).setDeletedList(null);}if (CollUtil.isEmpty(baseList) && CollUtil.isNotEmpty(targetList)) {List<TargetWrapper<T>> wrapperTargetList = targetList.stream().map(t -> new TargetWrapper<>(t, EnumType.DELETED)).collect(Collectors.toList());return new DiffResult<T>().setAddedList(wrapperTargetList).setChangedList(null).setDeletedList(null);}if (CollUtil.isNotEmpty(baseList) && CollUtil.isEmpty(targetList)) {List<TargetWrapper<T>> wrapperBaseList = baseList.stream().map(t -> new TargetWrapper<>(t, EnumType.DELETED)).collect(Collectors.toList());return new DiffResult<T>().setAddedList(null).setChangedList(null).setDeletedList(wrapperBaseList);}return null;}@Data@AllArgsConstructorpublic static class User {private Integer id;private String userName;private String address;private String email;}
}
4.ObjectComparator类
public class ObjectComparator<T> implements Comparator<T> {@Overridepublic int compare(T o1, T o2) {// 反射来动态获取对象的属性Field[] fields = o1.getClass().getDeclaredFields();for (Field field : fields) {field.setAccessible(true);try {Object value1 = field.get(o1);Object value2 = field.get(o2);if (!isEqual(value1, value2)) {return compareValues(value1, value2);}} catch (IllegalAccessException e) {e.printStackTrace();}}return 0;}private int compareValues(Object value1, Object value2) {if (value1 == null && value2 == null) {return 0;}if (value1 == null) {return -1;}if (value2 == null) {return 1;}if (value1 instanceof Comparable && value2 instanceof Comparable) {return ((Comparable) value1).compareTo(value2);}return 0;}private boolean isEqual(Object value1, Object value2) {if (value1 == null && value2 == null) {return true;}if (value1 == null || value2 == null) {return false;}return value1.equals(value2);}
}
5.Test单元测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class DiffListUtilApplicationTest {@Testpublic void test1() {List<DiffListUtil.User> userList = new ArrayList<>();DiffListUtil diffListUtil = new DiffListUtil();userList.add(new DiffListUtil.User(11,"John","hunan","hunan@faw.com"));userList.add(new DiffListUtil.User(22,"Tom","jilin","jilin@faw.com"));List<DiffListUtil.User> userListAfter = new ArrayList<>();userListAfter.add(new DiffListUtil.User(33,"John","hunan","beijing@faw.com"));userListAfter.add(new DiffListUtil.User(22,"Wudaiming","hunan","hunan@faw.com"));Function<DiffListUtil.User, Object> primaryKeyExtractor = user -> user.getId();//Comparator<DiffListUtil.User> userComparator = Comparator// .comparing(DiffListUtil.User::getId)// .thenComparing(DiffListUtil.User::getUserName)// .thenComparing(DiffListUtil.User::getAddress)// .thenComparing(DiffListUtil.User::getEmail);ObjectComparator<DiffListUtil.User> userComparator = new ObjectComparator<>();DiffListUtil.DiffResult<DiffListUtil.User> userDiffResult = diffListUtil.diffList(userList, userListAfter, primaryKeyExtractor, userComparator);System.out.println(userDiffResult);}
}