java集合diff算法

2018-11-15  本文已影响0人  cosinzhang

diff算法

比较2个集合对象,得出哪些是新增的、哪些是删除的、哪些是更新的

public class DiffUtil {
    @Data
    @Accessors(chain = true)
    public static class DiffResult<T> {
        /**
         * 新增对象列表
         */
        private List<T> addedList;
        /**
         * 修改后的对象列表
         */
        private List<T> changedList;
        /**
         * 已删除对象列表
         */
        private List<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   元素比较器
     * @param 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<T> addedList = new ArrayList<>();
        List<T> changedList = new ArrayList<>();
        List<T> deletedList = new ArrayList<>();

        //找出新增的 和需要更新的
        for (T target : targetList) {
            Object key = primaryKeyExtractor.apply(target);
            T base = baseMap.get(key);
            if(base == null){
                addedList.add(target);
            }else{
                baseMap.remove(key);
                if (elementComparator.compare(base, target) != 0) {
                    changedList.add(target);
                }
            }
        }

        //剩余的就是需要删除的
        Set<Entry<Object, T>> entrySet = baseMap.entrySet();
        if(CollectionUtils.isNotEmpty(entrySet)){
            for(Entry<Object, T> entry:entrySet){
                deletedList.add(entry.getValue());
            }
        }

        return new DiffResult<T>()
                .setAddedList(addedList)
                .setChangedList(changedList)
                .setDeletedList(deletedList);
    }


    /**
     * 检查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 (CollectionUtils.isEmpty(baseList) && CollectionUtils.isEmpty(targetList)) {
            return new DiffResult<T>()
                    .setAddedList(null)
                    .setChangedList(null)
                    .setDeletedList(null);
        }

        if (CollectionUtils.isEmpty(baseList) && CollectionUtils.isNotEmpty(targetList)) {
            return new DiffResult<T>()
                    .setAddedList(targetList)
                    .setChangedList(null)
                    .setDeletedList(null);
        }

        if (CollectionUtils.isNotEmpty(baseList) && CollectionUtils.isEmpty(targetList)) {
            return new DiffResult<T>()
                    .setAddedList(null)
                    .setChangedList(null)
                    .setDeletedList(baseList);
        }
        return null;
    }

    @Data
    @AllArgsConstructor
    public static class User {
        private Integer id;
        private String userName;
        private String realName;
    }
}
上一篇下一篇

猜你喜欢

热点阅读