首先看一下我的文件结构
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);
}
}