zoukankan      html  css  js  c++  java
  • 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     }
  • 相关阅读:
    什么是css权重
    html5 canvas画五角星(美国队长)
    从输入URL到页面加载发生了什么
    javascript之事件委托(转)
    javascript之常用排序算法
    javascript之闭包
    javascript二维数组的删除
    javascript之apply()、call()
    div+css两列布局与三列布局
    css处理水平居中问题(淘宝双飞翼布局)
  • 原文地址:https://www.cnblogs.com/HYV587/p/15654429.html
Copyright © 2011-2022 走看看