JAVA中DIFF算法实现
作者:编程路上的wdm
本文主要介绍了JAVA中DIFF算法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
首先看一下我的文件结构
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 { @Data public 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 @AllArgsConstructor public static class User { private Integer id; private String userName; private String address; private String email; } }
4.ObjectComparator类
public class ObjectComparator<T> implements Comparator<T> { @Override public 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 { @Test public 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); } }
到此这篇关于JAVA中DIFF算法实现的文章就介绍到这了,更多相关JAVA DIFF算法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!