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;
}
}
网友评论