JAVA中DIFF算法实现

 更新时间:2023年07月03日 14:46:02   作者:编程路上的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算法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java8中的LocalDateTime你会使用了吗

    Java8中的LocalDateTime你会使用了吗

    LocalDateTime 是 Java 8 中日期时间 API 提供的一个类,在日期和时间的表示上提供了更加丰富和灵活的支持,本文就来讲讲LocalDateTime的一些具体使用方法吧
    2023-05-05
  • java ReentrantLock详解

    java ReentrantLock详解

    这篇文章主要介绍了java ReentrantLock,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • Java类的初始化顺序的实现

    Java类的初始化顺序的实现

    类的初始化过程是在类加载阶段完成的,包括加载、验证、准备、解析和初始化等步骤,本文主要介绍了Java类的初始化顺序的实现,感兴趣的可以了解一下
    2023-12-12
  • maven helper jar包冲突的几种解决方法

    maven helper jar包冲突的几种解决方法

    maven Helper是排查jar包冲突的一大利器,jar包冲突大部分是由于引用了同一个jar的不同版本而导致的,本文主要介绍了maven helper jar包冲突的几种解决方法,感兴趣的可以了解一下
    2024-03-03
  • SpringMVC请求参数的使用总结

    SpringMVC请求参数的使用总结

    在日常使用SpringMVC进行开发的时候,有可能遇到前端各种类型的请求参数,本文主要接介绍了SpringMVC请求参数的使用总结,感兴趣的可以了解一下
    2021-06-06
  • java和jsp之间的request传值方法

    java和jsp之间的request传值方法

    这篇文章主要给大家介绍了关于java和jsp之间的request传值方法的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • Spring security自定义用户认证流程详解

    Spring security自定义用户认证流程详解

    这篇文章主要介绍了Spring security自定义用户认证流程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • idea在工具栏中显示快速创建包和类的图标的详细步骤

    idea在工具栏中显示快速创建包和类的图标的详细步骤

    点击需要创建包或者类的位置,在点击对用的图标就可以快速创建类或者包了,下面小编给大家介绍idea在工具栏中显示快速创建包和类的图标的详细步骤,感兴趣的朋友一起看看吧
    2024-02-02
  • JavaWeb实现简单查询商品功能

    JavaWeb实现简单查询商品功能

    这篇文章主要为大家详细介绍了JavaWeb实现简单查询商品功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-07-07
  • PageHelper插件实现一对多查询时的分页问题

    PageHelper插件实现一对多查询时的分页问题

    这篇文章主要介绍了PageHelper插件实现一对多查询时的分页问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04

最新评论