java 实现Diff算法


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

  1 public class DiffUtil {
  2     @Data
  3     @Accessors(chain = true)
  4     public static class DiffResult {
  5         /**
  6          * 新增对象列表
  7          */
  8         private List addedList;
  9         /**
 10          * 修改后的对象列表
 11          */
 12         private List changedList;
 13         /**
 14          * 已删除对象列表
 15          */
 16         private List deletedList;
 17     }
 18 
 19     /**
 20      * 对比两个List的元素
 21      * 

22 * 如果 baseList 的元素在 targetList 中存在 PrimaryKey 相等的元素并且 elementComparator 比较结果不相等,则将修改后的值添加到changedList列表中; 23 * 如果 baseList 的元素在 targetList 中不存在,将baseList中的元素添加到deletedList中; 24 * 如果 targetList 的元素在 baseList 中不存在,将targetList中的元素添加到addedList中; 25 *

26 * complexity: O(n) 27 * 28 * @param baseList 基础List(原来的List) 29 * @param targetList 目标List(最新的List) 30 * @param elementComparator 元素比较器 31 * @param primaryKeyExtractor 主键选择器 32 * @param 33 * @return 对比结果 34 */ 35 public static DiffResult diffList(List baseList, 36 List targetList, 37 @NotNull Function primaryKeyExtractor, 38 @NotNull Comparator elementComparator) { 39 40 DiffResult checkResult = checkEmptyAndReturn(baseList, targetList); 41 if (checkResult != null) { 42 return checkResult; 43 } 44 45 Map baseMap = new HashMap<>(4096); 46 for(T base : baseList){ 47 Object key = primaryKeyExtractor.apply(base); 48 baseMap.put(key,base); 49 } 50 51 List addedList = new ArrayList<>(); 52 List changedList = new ArrayList<>(); 53 List 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> entrySet = baseMap.entrySet(); 71 if(CollectionUtils.isNotEmpty(entrySet)){ 72 for(Map.Entry entry:entrySet){ 73 deletedList.add(entry.getValue()); 74 } 75 } 76 77 return new DiffResult() 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 90 * @return 91 */ 92 private static DiffResult checkEmptyAndReturn(List baseList, List targetList) { 93 94 if (CollectionUtils.isEmpty(baseList) && CollectionUtils.isEmpty(targetList)) { 95 return new DiffResult() 96 .setAddedList(null) 97 .setChangedList(null) 98 .setDeletedList(null); 99 } 100 101 if (CollectionUtils.isEmpty(baseList) && CollectionUtils.isNotEmpty(targetList)) { 102 return new DiffResult() 103 .setAddedList(targetList) 104 .setChangedList(null) 105 .setDeletedList(null); 106 } 107 108 if (CollectionUtils.isNotEmpty(baseList) && CollectionUtils.isEmpty(targetList)) { 109 return new DiffResult() 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 baseList=new ArrayList<>();
 5         List 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 function=mbi-> mbi.getId();
19         // 元素比较器
20         DiffUtil.DiffResult  result= DiffUtil.diffList(baseList,targetList,function,new Comparator(){
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     }