java 实现Diff算法

作用:比较新旧数组,得到新增的元素,删除的元素,更新的元素

  1 public class DiffUtil {
  2     @Data
  3     @Accessors(chain = true)
  4     public static class DiffResult<T> {
  5         /**
  6          * 新增对象列表
  7          */
  8         private List<T> addedList;
  9         /**
 10          * 修改后的对象列表
 11          */
 12         private List<T> changedList;
 13         /**
 14          * 已删除对象列表
 15          */
 16         private List<T> deletedList;
 17     }
 18 
 19     /**
 20      * 对比两个List的元素
 21      * <p>
 22      * 如果 baseList 的元素在 targetList 中存在 PrimaryKey 相等的元素并且 elementComparator 比较结果不相等,则将修改后的值添加到changedList列表中;
 23      * 如果 baseList 的元素在 targetList 中不存在,将baseList中的元素添加到deletedList中;
 24      * 如果 targetList 的元素在 baseList 中不存在,将targetList中的元素添加到addedList中;
 25      * <p>
 26      * complexity: O(n)
 27      *
 28      * @param baseList            基础List(原来的List)
 29      * @param targetList          目标List(最新的List)
 30      * @param elementComparator   元素比较器
 31      * @param primaryKeyExtractor 主键选择器
 32      * @param <T>
 33      * @return 对比结果
 34      */
 35     public static <T> DiffResult<T> diffList(List<T> baseList,
 36                                              List<T> targetList,
 37                                              @NotNull Function<T, Object> primaryKeyExtractor,
 38                                              @NotNull Comparator<T> elementComparator) {
 39 
 40         DiffResult<T> checkResult = checkEmptyAndReturn(baseList, targetList);
 41         if (checkResult != null) {
 42             return checkResult;
 43         }
 44 
 45         Map<Object,T> baseMap = new HashMap<>(4096);
 46         for(T base : baseList){
 47             Object key = primaryKeyExtractor.apply(base);
 48             baseMap.put(key,base);
 49         }
 50 
 51         List<T> addedList = new ArrayList<>();
 52         List<T> changedList = new ArrayList<>();
 53         List<T> deletedList = new ArrayList<>();
 54 
 55         //找出新增的 和需要更新的
 56         for (T target : targetList) {
 57             Object key = primaryKeyExtractor.apply(target);
 58             T base = baseMap.get(key);
 59             if(base == null){
 60                 addedList.add(target);
 61             }else{
 62                 baseMap.remove(key);
 63                 if (elementComparator.compare(base, target) != 0) {
 64                     changedList.add(target);
 65                 }
 66             }
 67         }
 68 
 69         //剩余的就是需要删除的
 70         Set<Map.Entry<Object, T>> entrySet = baseMap.entrySet();
 71         if(CollectionUtils.isNotEmpty(entrySet)){
 72             for(Map.Entry<Object, T> entry:entrySet){
 73                 deletedList.add(entry.getValue());
 74             }
 75         }
 76 
 77         return new DiffResult<T>()
 78                 .setAddedList(addedList)
 79                 .setChangedList(changedList)
 80                 .setDeletedList(deletedList);
 81     }
 82 
 83 
 84     /**
 85      * 检查baseList 和 targetList 为empty(null||size==0)的情况
 86      *
 87      * @param baseList
 88      * @param targetList
 89      * @param <T>
 90      * @return
 91      */
 92     private static <T> DiffResult<T> checkEmptyAndReturn(List<T> baseList, List<T> targetList) {
 93 
 94         if (CollectionUtils.isEmpty(baseList) && CollectionUtils.isEmpty(targetList)) {
 95             return new DiffResult<T>()
 96                     .setAddedList(null)
 97                     .setChangedList(null)
 98                     .setDeletedList(null);
 99         }
100 
101         if (CollectionUtils.isEmpty(baseList) && CollectionUtils.isNotEmpty(targetList)) {
102             return new DiffResult<T>()
103                     .setAddedList(targetList)
104                     .setChangedList(null)
105                     .setDeletedList(null);
106         }
107 
108         if (CollectionUtils.isNotEmpty(baseList) && CollectionUtils.isEmpty(targetList)) {
109             return new DiffResult<T>()
110                     .setAddedList(null)
111                     .setChangedList(null)
112                     .setDeletedList(baseList);
113         }
114         return null;
115     }
116 
117     @Data
118     @AllArgsConstructor
119     public static class User {
120         private Integer id;
121         private String userName;
122         private String realName;
123     }
 1 案列:
 2  @Test
 3     void test04(){
 4         List<DiffUtil.User> baseList=new ArrayList<>();
 5         List<DiffUtil.User> targetList=new ArrayList<>();
 6         DiffUtil.User user=new DiffUtil.User(1,"a","b");
 7         DiffUtil.User user1=new DiffUtil.User(2,"a","b");
 8         baseList.add(user);
 9         baseList.add(user1);
10         DiffUtil.User user2=new DiffUtil.User(3,"a","b");
11         DiffUtil.User user3=new DiffUtil.User(4,"a","b");
12         DiffUtil.User user4=new DiffUtil.User(1,"abb","bbbb");
13 
14         targetList.add(user4);
15         targetList.add(user2);
16         targetList.add(user3);
17         // 主键选择器
18         Function<DiffUtil.User,Object> function=mbi-> mbi.getId();
19         // 元素比较器
20         DiffUtil.DiffResult<DiffUtil.User>  result= DiffUtil.diffList(baseList,targetList,function,new Comparator<DiffUtil.User>(){
21             @Override
22             public int compare(DiffUtil.User o1, DiffUtil.User o2) {
23                 int i = 0;
24                 // 自定義比較規則,帥選出更新的元素
25                 if (o1.getUserName().equals(o2.getUserName())){
26                     i=0;
27                 }else {
28                     i=1;
29                 }
30                 return i;
31 
32             }
33         });
34 
35         System.out.println(result.getAddedList());
36         System.out.println(result.getDeletedList());
37         System.out.println(result.getChangedList());
38         
39         // 通過以下操作可得到最終更新後的新數組
40         baseList.addAll(result.getAddedList());
41         baseList.removeAll(result.getDeletedList());
42         baseList.forEach(mbi->{
43             for (DiffUtil.User obj:result.getChangedList()){
44                 if (mbi.getId()==obj.getId()){
45                    mbi.setRealName(obj.getRealName());
46                    mbi.setUserName(obj.getUserName());
47                 }
48             }
49         });
50         System.out.println(baseList);
51     }
原文地址:https://www.cnblogs.com/HYV587/p/15654429.html