场景:主表关联数据,例如附件、关联人员等信息,前端会携带表单信息全量提交,后台无法判断数据中是否有新增,更新与删除数据,此工具设计为解决此类问题。
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());
}
}
如有不合适或者错误地方欢迎各位大佬留言纠正
评论区