侧边栏壁纸
  • 累计撰写 17 篇文章
  • 累计创建 10 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

diff工具,对比原数据与更新数据,主要用于增量更新

骑摩托的程序员
2023-01-18 / 0 评论 / 1 点赞 / 880 阅读 / 708 字

场景:主表关联数据,例如附件、关联人员等信息,前端会携带表单信息全量提交,后台无法判断数据中是否有新增,更新与删除数据,此工具设计为解决此类问题。

package utils;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author zhang
 * @Description diff工具,对比原数据与更新数据,主要用于增量更新
 * @date 2023/1/18 10:38
 **/
public class DiffUtil<T, R> {

    /**
     * diff方法返回key
     *  ADD     为新增数据key
     *  UPDATE  为更新数据key
     *  DELETE  为删除数据key
     */
    public static final String KEY_ADD = "ADD_DATA";
    public static final String KEY_UPDATE = "UPDATE_DATA";
    public static final String KEY_DELETE = "DELETE_DATA";

    /**
     * 对比方法,放回原数据与更新数据对比之后需要删除(元素为R)、添加(元素为T)、修改(元素为T)的集合
     * eg:         Map extracted = new DiffUtil<User, Long>().diff(list1, list2, User::getId, e -> e.getId() == null, e -> e.getId() != null);
     * @param original 源数据
     * @param revised 改变数据
     * @param funA 获取删除资源的唯一信息(主键)
     *             eg:   自定义类: User::getId
     *                   包装类:  e -> e.longValue()
     * @param addPredicate 新增数据过滤filter条件,允许为null,不返回新增数据 eg:      e -> e.getId() == null
     * @param updatePredicate 更新数据过滤filter条件,允许为null,不返回更新数据 eg:  e -> e.getId() != null
     * @return 返回k,v三类数据,k在此类常量中定义
     */
    public Map diff(List<T> original, List<T> revised, Function<T, R> funA, Predicate<? super T> addPredicate, Predicate<? super T> updatePredicate) {
        Map map = new HashMap<>();
        Objects.requireNonNull(original, "original must not be null");
        Objects.requireNonNull(revised, "revised must not be null");
        if (original.isEmpty()) {
            map.put(KEY_ADD, revised);
            return map;
        }
        if (revised.isEmpty()) {
            map.put(KEY_DELETE, original.stream().map(funA).collect(Collectors.toList()));
            return map;
        }
        if (funA != null) {
            map.put(KEY_DELETE, diffDel(original, revised, funA));
        }
        //复制集合removeAll不改变原参数数据
        List<T> copyRevised = new ArrayList<>(revised);
        copyRevised.removeAll(original);
        if (addPredicate != null) map.put(KEY_ADD, diffFilter(copyRevised, addPredicate));
        if (updatePredicate != null) map.put(KEY_UPDATE, diffFilter(copyRevised, updatePredicate));
        return map;
    }

    /**
     * 对比获取revised中存在,且original中不存在的数据
     *
     * @param original
     * @param revised
     * @param funA
     * @return
     */
    private List<R> diffDel(List<T> original, List<T> revised, Function<T, R> funA) {
        Objects.requireNonNull(original, "original must not be null");
        Objects.requireNonNull(revised, "revised must not be null");
        List<R> revisedList = revised.stream().map(funA).collect(Collectors.toList());
        List<R> delList = original.stream().map(funA).filter(m -> !revisedList.contains(m)).collect(Collectors.toList());
        return delList;
    }

    /**
     * revised与original取差集,之后根据predicate过滤数据
     *
     * @param revised
     * @param predicate
     * @return
     */
    private List<T> diffFilter(List<T> revised, Predicate<? super T> predicate) {
        Objects.requireNonNull(revised, "revised must not be null");
        return revised.stream().filter(predicate).collect(Collectors.toList());
    }

}

如有不合适或者错误地方欢迎各位大佬留言纠正

1

评论区