• 一个自己写的判断2个相同对象的属性值差异的工具类


    在后台管理系统中经常会有需要记录用户操作日志的需求,其中需要最好能记录用户修改了哪些字段的数据(变更前,变更后),这个时候就需要抽取一个工具的类来处理这件事。

    20180105进行优化升级:1、增加对基本类型的集合的对比。2、优化反射的缓存。3、增加dto+集合的混合对比方法。

    结果样例:

    [{
            "column": "name",
            "difference": {
                "newValue": "李四",
                "oldValue": "张三"
            }
        }, {
            "column": "arr",
            "difference": {
                "newValue": [{
                        "column": "delete",
                        "difference": {
                            "newValue": null,
                            "oldValue": [1]
                        }
                    }, {
                        "column": "add",
                        "difference": {
                            "newValue": [4],
                            "oldValue": null
                        }
                    }
                ],
                "oldValue": null
            }
        }
    ]

    工具类:

    
    
      1 import java.io.Serializable;
      2 import java.lang.reflect.Field;
      3 import java.lang.reflect.InvocationTargetException;
      4 import java.lang.reflect.Method;
      5 import java.math.BigDecimal;
      6 import java.util.ArrayList;
      7 import java.util.Collection;
      8 import java.util.HashMap;
      9 import java.util.HashSet;
     10 import java.util.List;
     11 import java.util.Map;
     12 import java.util.Set;
     13 import java.util.regex.Matcher;
     14 import java.util.regex.Pattern;
     15 
     16 import org.reflections.ReflectionUtils;
     17 
     18 import com.alibaba.fastjson.JSON;
     19 import com.alibaba.fastjson.serializer.SerializerFeature;
     20 
     21 import lombok.AllArgsConstructor;
     22 import lombok.Builder;
     23 import lombok.Getter;
     24 import lombok.NoArgsConstructor;
     25 import lombok.Setter;
     26 import lombok.extern.slf4j.Slf4j;
     27 
     28 /**
     29  * 比较2个对象的值的不同的情况
     30  * 
     31  * 注意:对声明值比较类为基本类型的但传入非基本类型的话不保证程序和数据的正确性。
     32  * 
     33  * 目前支持的比较类型有:
     34  * 1、普通dto(不包含复杂对象)的比较  
     35  *         可用的方法有:
     36  *             {@link CompareDifferenceUtil#isDifference(Object, Object)}
     37  *             {@link CompareDifferenceUtil#isDifferenceSelective(Object, Object)}
     38  *             {@link CompareDifferenceUtil#compare(Object, Object)}
     39  *             {@link CompareDifferenceUtil#compareSelective(Object, Object)}
     40  *             {@link CompareDifferenceUtil#getDiffernceList(Object, Object)}
     41  *             {@link CompareDifferenceUtil#getDiffernceListSelective(Object, Object)}
     42  * 2、普通基本类型的集合的比较
     43  *         可用的方法有:
     44  *             {@link CompareDifferenceUtil#isDifference(Collection, Collection)}
     45  *             {@link CompareDifferenceUtil#compareCollection(Collection, Collection)}
     46  *             {@link CompareDifferenceUtil#compareCollectionSelective(Collection, Collection)}
     47  * 3、普通dto(不包含复杂对象) + 普通基本类型的集合的比较
     48  *         可用的方法有:
     49  *             {@link CompareDifferenceUtil#compare(Object, Object, CompareCollectionDto...)}
     50  *             {@link CompareDifferenceUtil#compareSelective(Object, Object, CompareCollectionDto...)}
     51  * 4、主从一对一的比较
     52  *         可用的方法有:
     53  *             {@link CompareDifferenceUtil#compareMainAndDetail(Object, Object, String, Object, Object)}
     54  *             {@link CompareDifferenceUtil#compareMainAndDetailSelective(Object, Object, String, Object, Object)}
     55  * 
     56  * 
     57  * @author yangzhilong
     58  */
     59 @Slf4j
     60 public class CompareDifferenceUtil {
     61     private static final String ADD = "add";
     62     private static final String UPDATE = "update";
     63     private static final String DELETE = "delete";
     64     private static final Set<String> ignoreFileds = new HashSet<>(5);
     65     
     66     private static final Map<String,Set<Field>> fieldCache = new HashMap<>();
     67     private static final Map<String,Set<Method>> methodCache = new HashMap<>();
     68     
     69     static {
     70         ignoreFileds.add("serialVersionUID");
     71         ignoreFileds.add("createBy");
     72         ignoreFileds.add("createTime");
     73         ignoreFileds.add("updateBy");
     74         ignoreFileds.add("updateTime");
     75     }
     76     
     77     /**
     78      * 比较2个对象是否有差异
     79      * @param oldObj
     80      * @param newObj
     81      * @return
     82      */
     83     public static boolean isDifference(Object oldObj, Object newObj) {
     84         return !getDiffernceList(oldObj, newObj, true, false).isEmpty();
     85     }
     86     
     87     /**
     88      * 比较2个对象是否有差异(新增中的属性为null的话跳过比较该属性)
     89      * @param oldObj
     90      * @param newObj
     91      * @return
     92      */
     93     public static boolean isDifferenceSelective(Object oldObj, Object newObj) {
     94         return !getDiffernceList(oldObj, newObj, true, true).isEmpty();
     95     }
     96     
     97     /**
     98      * 比较2个集合是否有差异(基本类型)
     99      * @param oldCollection
    100      * @param newCollection
    101      * @return
    102      */
    103     public static <T> boolean isDifference(Collection<T> oldCollection, Collection<T> newCollection) {
    104         return !compareCollectionList(oldCollection, newCollection).isEmpty();
    105     }
    106     
    107     /**
    108      * 得到变化的列的数据
    109      * @param oldObj
    110      * @param newObj
    111      * @return
    112      */
    113     public static List<DifferenceWapper> getDiffernceList(Object oldObj, Object newObj) {
    114         return getDiffernceList(oldObj, newObj, false, false);
    115     }
    116     
    117     /**
    118      * 得到变化的列的数据(新增中的属性为null的话跳过比较该属性)
    119      * @param oldObj
    120      * @param newObj
    121      * @return
    122      */
    123     public static List<DifferenceWapper> getDiffernceListSelective(Object oldObj, Object newObj) {
    124         return getDiffernceList(oldObj, newObj, false, true);
    125     }
    126     
    127     /**
    128      * 比较主从对象的复杂类型的数据(主从一对一关系)
    129      * @param oldMainObj 主对象的老对象
    130      * @param newMainObj 助对象的新对象
    131      * @param detailAttrName 主对象中detail的属性名称
    132      * @param oldDetailObj 明细对象的老对象(复杂类型的对象,但非集合)
    133      * @param newDetailObj 明细对象的新对象(复杂类型的对象,但非集合)
    134      * @return
    135      */
    136     public static String compareMainAndDetail(Object oldMainObj, Object newMainObj, String detailAttrName, Object oldDetailObj, Object newDetailObj) {
    137         return aggregateDataAndConvertToJson(getDiffernceList(oldMainObj, newMainObj), detailAttrName , getDiffernceList(oldDetailObj, newDetailObj));
    138     }
    139     
    140     /**
    141      * 比较主从对象的复杂类型的数据(主从一对一关系)
    142      * @param oldMainObj 主对象的老对象
    143      * @param newMainObj 助对象的新对象
    144      * @param detailAttrName 主对象中detail的属性名称
    145      * @param oldDetailObj 明细对象的老对象(复杂类型的对象,但非集合)
    146      * @param newDetailObj 明细对象的新对象(复杂类型的对象,但非集合)
    147      * @return
    148      */
    149     public static String compareMainAndDetailSelective(Object oldMainObj, Object newMainObj, String detailAttrName, Object oldDetailObj, Object newDetailObj) {
    150         return aggregateDataAndConvertToJson(getDiffernceListSelective(oldMainObj, newMainObj), detailAttrName , getDiffernceListSelective(oldDetailObj, newDetailObj));
    151     }
    152     
    153     /**
    154      * 得到2个相同对象的相同字段的不同的值
    155      * 
    156      * @param oldObj 变更前对象,不能为null
    157      * @param newObj 变更后对象,不能为null
    158      * @return
    159      */
    160     public static String compare(Object oldObj, Object newObj) {
    161         List<DifferenceWapper> result = getDiffernceList(oldObj, newObj);
    162         if(!result.isEmpty()) {
    163             return JSON.toJSONString(result, SerializerFeature.WriteMapNullValue);
    164         }
    165         return null;
    166     }
    167 
    168     /**
    169      * 得到2个相同对象的相同字段的不同的值,newObj中有属性为null,就跳过这个属性
    170      *
    171      * @param oldObj 变更前对象,不能为null
    172      * @param newObj 变更后对象,不能为null
    173      * @return
    174      */
    175     public static String compareSelective(Object oldObj, Object newObj) {
    176         List<DifferenceWapper> result = getDiffernceListSelective(oldObj, newObj);
    177         if(!result.isEmpty()) {
    178             return JSON.toJSONString(result, SerializerFeature.WriteMapNullValue);
    179         }
    180         return null;
    181     }
    182     
    183     /**
    184      * 得到2个对象以及相关list的差异
    185      * @param <T>
    186      * @param oldObj
    187      * @param newObj
    188      * @param array 多个基本类型的集合的包装类
    189      * @return 
    190      */
    191     @SuppressWarnings("unchecked")
    192     public static <T> String compare(Object oldObj, Object newObj, CompareCollectionDto<T>... array) {
    193         return baseCompare(oldObj, newObj, false, array);
    194     }
    195 
    196     /**
    197      * 得到2个对象以及相关list的差异,如果有新list集合为空,则忽略此属性
    198      * @param <T>
    199      * @param oldObj
    200      * @param newObj
    201      * @param array 多个基本类型的集合的包装类
    202      * @return
    203      */
    204     @SuppressWarnings("unchecked")
    205     public static <T> String compareSelective(Object oldObj, Object newObj, CompareCollectionDto<T>... array) {
    206         return baseCompare(oldObj, newObj, true, array);
    207     }
    208     
    209     /**
    210      * 比较2个字符串集合的差异(只支持基本类型)
    211      * @param <T>
    212      * @param oldCollection
    213      * @param newCollection
    214      * @return
    215      */
    216     public static <T> String compareCollection(Collection<T> oldCollection, Collection<T> newCollection) {
    217         List<DifferenceWapper> result = compareCollectionList(oldCollection, newCollection);
    218         if(result.isEmpty()) {
    219             return null;
    220         }
    221         return JSON.toJSONString(result, SerializerFeature.WriteMapNullValue);
    222     }
    223 
    224     /**
    225      * 比较2个字符串集合的差异(只支持基本类型),如果newCollection为null,则忽略比较
    226      * @param <T>
    227      * @param oldCollection
    228      * @param newCollection
    229      * @return
    230      */
    231     public static <T> String compareCollectionSelective(Collection<T> oldCollection, Collection<T> newCollection) {
    232         List<DifferenceWapper> result = compareCollectionListSelective(oldCollection, newCollection);
    233         if(result.isEmpty()) {
    234             return null;
    235         }
    236         return JSON.toJSONString(result, SerializerFeature.WriteMapNullValue);
    237     }
    238     
    239     /**
    240      * 基本的检查
    241      * @param oldObj
    242      * @param newObj
    243      * @param selective
    244      * @param array
    245      * @return
    246      */
    247     @SuppressWarnings("unchecked")
    248     private static <T> String baseCompare(Object oldObj, Object newObj, boolean selective, CompareCollectionDto<T>... array) {
    249         if(null==array || array.length == 0) {
    250             throw new RuntimeException("集合对象的数组不能为空");
    251         }
    252         List<DifferenceWapper> result = getDiffernceList(oldObj, newObj, false, selective);
    253         for(CompareCollectionDto<T> dto : array) {
    254             List<DifferenceWapper> cr = null;
    255             if(selective) {
    256                 cr = compareCollectionListSelective(dto.getOldCollection(), dto.getNewCollection());
    257             } else {
    258                 cr = compareCollectionList(dto.getOldCollection(), dto.getNewCollection());
    259             }
    260             
    261             if(!cr.isEmpty()) {
    262                 DifferenceWapper wapper = DifferenceWapper.builder().column(dto.getFiledName())
    263                         .difference(Difference.builder().newValue(cr).build()).build();
    264                 result.add(wapper);
    265             }
    266         }
    267         if(!result.isEmpty()) {
    268             return JSON.toJSONString(result, SerializerFeature.WriteMapNullValue);
    269         }
    270         return null;
    271     }
    272     
    273     /**
    274      * 
    275      * @param oldObj
    276      * @param newObj
    277      * @param onlyCheck 是否仅校验(遇到不同则立刻返回)
    278      * @param selective true代表如果newObj的属性的值为null则跳过该属性比较
    279      * @return
    280      */
    281     private static List<DifferenceWapper> getDiffernceList(Object oldObj, Object newObj, boolean onlyCheck, boolean selective) {
    282         List<DifferenceWapper> result = new ArrayList<>();
    283         
    284         // 是否是创建类型的比较
    285         boolean isCreate = false;
    286         if(oldObj == null) {
    287             isCreate = true;
    288         } else {
    289             if(null == newObj) {
    290                 throw new RuntimeException("更改后的对象不能为null");
    291             }
    292         }
    293         if(!isCreate && !newObj.getClass().equals(oldObj.getClass())) {
    294             throw new RuntimeException("两个需要比较的对象必须为同一类型");
    295         }
    296         // 同一个对象就没必要对比了
    297         if(oldObj == newObj) {
    298             return result;
    299         }
    300         
    301         Set<Field> fields = getField(newObj.getClass());
    302         Set<Method> methods = getMethod(newObj.getClass());
    303         
    304         if(null != fields && !fields.isEmpty()) {
    305             String methodName = null;
    306             String fieldName = null;
    307             for(Field field : fields) {
    308                 if(ignoreFileds.contains(field.getName())) {
    309                     continue;
    310                 }
    311                 fieldName = field.getName();
    312                 methodName = "get".concat(fieldName.substring(0, 1).toUpperCase()).concat(fieldName.substring(1));
    313                 
    314                 Method method = filterMethod(methods, methodName);
    315                 if(null == method) {
    316                     // 是小boolean类型则需要特殊处理
    317                     if("boolean".equals(field.getType().getTypeName())) {
    318                         if(fieldName.startsWith("is")) {
    319                             // 如果第三位是大写
    320                             boolean upper = isUpperString(fieldName.substring(2, 3));
    321                             if(upper) {
    322                                 methodName = fieldName;
    323                             } else {
    324                                 methodName = "is".concat(fieldName.substring(0, 1).toUpperCase()).concat(fieldName.substring(1));
    325                             }
    326                         } else {
    327                             methodName = "is".concat(fieldName.substring(0, 1).toUpperCase()).concat(fieldName.substring(1));
    328                         }
    329                         method = filterMethod(methods, methodName);
    330                     }
    331                     if(null == method) {
    332                         continue;
    333                     }
    334                 }
    335                 try {
    336                     Object oldValue = null;
    337                     if(!isCreate) {
    338                         oldValue = method.invoke(oldObj);
    339                     }
    340                     Object newValue = method.invoke(newObj);
    341                     if(null == oldValue) {
    342                         if(null != newValue) {
    343                             result.add(DifferenceWapper.builder().column(fieldName).difference(Difference.builder().newValue(newValue).oldValue(oldValue).build()).build());
    344                         }
    345                     } else {
    346                         if(null != newValue) {
    347                             // 处理0.0和0的不同
    348                             if(newValue instanceof BigDecimal){
    349                                 BigDecimal newValue1 = (BigDecimal) newValue;
    350                                 BigDecimal oldValue1 = (BigDecimal) oldValue;
    351                                 if(newValue1.compareTo(oldValue1) != 0){
    352                                     result.add(DifferenceWapper.builder().column(fieldName).difference(Difference.builder().newValue(newValue).oldValue(oldValue).build()).build());
    353                                 }
    354                             } else if(!oldValue.equals(newValue)) {
    355                                 result.add(DifferenceWapper.builder().column(fieldName).difference(Difference.builder().newValue(newValue).oldValue(oldValue).build()).build());
    356                             }
    357                         } else {
    358                             if(!selective) {
    359                                 result.add(DifferenceWapper.builder().column(fieldName).difference(Difference.builder().newValue(newValue).oldValue(oldValue).build()).build());
    360                             }
    361                         }
    362                     }
    363                 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
    364                     log.error("反射调用get方法异常", e);
    365                     throw new RuntimeException(e);
    366                 }
    367                 /**
    368                  * 如果仅仅校验是否不同,则提前返回
    369                  */
    370                 if(onlyCheck && !result.isEmpty()) {
    371                     return result;
    372                 }
    373             }
    374         }
    375         return result;
    376     }
    377 
    378     /**
    379      * 获取类的所有字段
    380      * @param type
    381      * @return
    382      */
    383     @SuppressWarnings("unchecked")
    384     private static Set<Field> getField(Class<?> type) {
    385         String className = type.getName();
    386         if(fieldCache.get(className) == null || fieldCache.get(className).isEmpty()) {
    387             synchronized (className) {
    388                 if(fieldCache.get(className) == null || fieldCache.get(className).isEmpty()) {
    389                     fieldCache.put(className, ReflectionUtils.getAllFields(type));
    390                 }
    391             }
    392         }
    393         return fieldCache.get(className);
    394     }
    395     
    396     /**
    397      * 获取类的所有方法
    398      * @param type
    399      * @return
    400      */
    401     @SuppressWarnings("unchecked")
    402     private static Set<Method> getMethod(Class<?> type) {
    403         String className = type.getName();
    404         if(methodCache.get(className) == null || methodCache.get(className).isEmpty()) {
    405             synchronized (className) {
    406                 if(methodCache.get(className) == null || methodCache.get(className).isEmpty()) {
    407                     methodCache.put(className, ReflectionUtils.getAllMethods(type));
    408                 }
    409             }
    410         }
    411         return methodCache.get(className);
    412     }
    413     
    414     /**
    415      * 比较2个字符串集合的差异(只支持基本类型)
    416      * @param <T>
    417      * @param oldCollection
    418      * @param newCollection
    419      * @return
    420      */
    421     private static <T> List<DifferenceWapper> compareCollectionList(Collection<T> oldCollection, Collection<T> newCollection) {
    422         String flag = UPDATE;
    423         if(null==oldCollection || oldCollection.isEmpty()) {
    424             if(null==newCollection || newCollection.isEmpty()) {
    425                 throw new RuntimeException("两个需要比较的集合不能都为空");
    426             }
    427             flag = ADD;
    428         } else {
    429             if(null==newCollection || newCollection.isEmpty()) {
    430                 flag = DELETE;
    431             }
    432         }
    433         
    434         if(ADD.equals(flag)) {
    435             return compareCollectionAdd(newCollection);
    436         } else if(DELETE.equals(flag)) {
    437             return compareCollectionDelete(oldCollection);
    438         } else {
    439             return compareCollectionUpdate(oldCollection, newCollection);
    440         }
    441     }
    442 
    443     /**
    444      * 比较2个字符串集合的差异(只支持基本类型),如果newCollection为null,则忽略比较
    445      * @param <T>
    446      * @param oldCollection
    447      * @param newCollection
    448      * @return
    449      */
    450     private static <T> List<DifferenceWapper> compareCollectionListSelective(Collection<T> oldCollection, Collection<T> newCollection) {
    451         String flag = UPDATE;
    452         if(null==oldCollection || oldCollection.isEmpty()) {
    453             if(null==newCollection || newCollection.isEmpty()) {
    454                 return new ArrayList<>();
    455             }
    456             flag = ADD;
    457         } else {
    458             if(null==newCollection || newCollection.isEmpty()) {
    459                 return new ArrayList<>();
    460             }
    461         }
    462 
    463         if(ADD.equals(flag)) {
    464             return compareCollectionAdd(newCollection);
    465         } else if(DELETE.equals(flag)) {
    466             return compareCollectionDelete(oldCollection);
    467         } else {
    468             return compareCollectionUpdate(oldCollection, newCollection);
    469         }
    470     }
    471     
    472     /**
    473      * 新增
    474      * @param newCollection
    475      * @return
    476      */
    477     private static <T> List<DifferenceWapper> compareCollectionAdd(Collection<T> newCollection) {
    478         List<DifferenceWapper> result = new ArrayList<>(1);
    479         DifferenceWapper diff = new DifferenceWapper();
    480         Difference difference = new Difference();
    481         difference.setNewValue(newCollection);
    482         diff.setColumn("add");
    483         diff.setDifference(difference);
    484         result.add(diff);
    485         return result;
    486     }
    487     
    488     /**
    489      * 删除
    490      * @param oldCollection
    491      * @return
    492      */
    493     private static <T> List<DifferenceWapper> compareCollectionDelete(Collection<T> oldCollection) {
    494         List<DifferenceWapper> result = new ArrayList<>(1);
    495         DifferenceWapper diff = new DifferenceWapper();
    496         Difference difference = new Difference();
    497         difference.setOldValue(oldCollection);
    498         diff.setColumn("delete");
    499         diff.setDifference(difference);
    500         result.add(diff);
    501         return result;
    502     }
    503     
    504     /**
    505      * 更新
    506      * @param oldCollection
    507      * @param newCollection
    508      * @return
    509      */
    510     private static <T> List<DifferenceWapper> compareCollectionUpdate(Collection<T> oldCollection, Collection<T> newCollection) {
    511         List<DifferenceWapper> ret = new ArrayList<>();
    512         
    513         Set<T> result = new HashSet<>();
    514         Set<T> oldSet = new HashSet<>();
    515         oldSet.addAll(oldCollection);
    516         Set<T> newSet = new HashSet<>();
    517         newSet.addAll(newCollection);
    518         
    519         //取交集
    520         result.addAll(oldCollection);
    521         result.retainAll(newCollection);
    522         
    523         //没有变更
    524         if(result.size()==newSet.size() && result.size()==oldSet.size()) {
    525             return ret;
    526         }
    527         
    528         //被删除的
    529         //取差集
    530         oldSet.removeAll(result);
    531         
    532         //新增的
    533         //取差集
    534         newSet.removeAll(result);
    535         
    536         if(!oldSet.isEmpty()) {
    537             DifferenceWapper diff = new DifferenceWapper();
    538             Difference difference = new Difference();
    539             difference.setOldValue(oldSet);
    540             diff.setColumn("delete");
    541             diff.setDifference(difference);
    542             ret.add(diff);
    543         }
    544         if(!newSet.isEmpty()) {
    545             DifferenceWapper diff = new DifferenceWapper();
    546             Difference difference = new Difference();
    547             difference.setNewValue(newSet);
    548             diff.setColumn("add");
    549             diff.setDifference(difference);
    550             ret.add(diff);
    551         }
    552         
    553         return ret;
    554     }
    555     
    556     /**
    557      * 过滤方法
    558      * @param methods
    559      * @param methodName
    560      * @return
    561      */
    562     private static Method filterMethod(Set<Method> methods, String methodName) {
    563         if(null != methods && !methods.isEmpty()) {
    564             for(Method method : methods) {
    565                 if(method.getName().equals(methodName)) {
    566                     return method;
    567                 }
    568             }
    569         }
    570         return null;
    571     }
    572     
    573     /**
    574      * 匹配是否是大写字母
    575      * @param str
    576      * @return
    577      */
    578     private static boolean isUpperString(String str) {
    579         Pattern p = Pattern.compile("[A-Z]");
    580         Matcher matcher = p.matcher(str);
    581         return matcher.matches();
    582     }
    583     
    584     /**
    585      * 聚合主和明细数据的变更记录
    586      * @param main
    587      * @param attrName 显示在主对象里的属性
    588      * @param detail 明细对象的属性差异的list
    589      */
    590     private static List<DifferenceWapper> aggregateData(List<DifferenceWapper> main, String attrName, List<DifferenceWapper> detail) {
    591         if(null != detail && !detail.isEmpty()) {
    592             if(null == main || main.isEmpty()) {
    593                 main = new ArrayList<>(1);
    594             }
    595             main.add(DifferenceWapper.builder().column(attrName).difference(Difference.builder().newValue(detail).build()).build());
    596         }
    597         return main;
    598     }
    599     
    600     /**
    601      * 聚合主和明细数据的变更记录并转换成json
    602      * @param main
    603      * @param attrName 显示在主对象里的属性
    604      * @param detail 明细对象的属性差异的list
    605      */
    606     private static String aggregateDataAndConvertToJson(List<DifferenceWapper> main, String attrName, List<DifferenceWapper> detail) {
    607         List<DifferenceWapper> result = aggregateData(main, attrName, detail);
    608         if(null!=result && !result.isEmpty()) {
    609             return JSON.toJSONString(result, SerializerFeature.WriteMapNullValue);
    610         }
    611         return null;
    612     }
    613     
    614     @Getter
    615     @Setter
    616     @Builder
    617     @NoArgsConstructor
    618     @AllArgsConstructor
    619     static class DifferenceWapper implements Serializable {
    620         private static final long serialVersionUID = -3369182406683473741L;
    621         private String column;
    622         private Difference difference;
    623     }
    624     
    625     @Getter
    626     @Setter
    627     @Builder
    628     @NoArgsConstructor
    629     @AllArgsConstructor
    630     static class Difference implements Serializable{
    631         private static final long serialVersionUID = 2478199484126795290L;
    632         
    633         private Object oldValue;
    634         private Object newValue;
    635     }
    636     
    637 }
    
    

    辅助DTO类:

     1 package com.longge.utils;
     2 
     3 import java.io.Serializable;
     4 import java.util.Collection;
     5 
     6 import lombok.AllArgsConstructor;
     7 import lombok.Builder;
     8 import lombok.Getter;
     9 import lombok.NoArgsConstructor;
    10 import lombok.Setter;
    11 
    12 /**
    13  * 集合类型的属性的比较包装类
    14  * @author yangzhilong
    15  *
    16  * @param <T>
    17  */
    18 @Getter
    19 @Setter
    20 @Builder
    21 @NoArgsConstructor
    22 @AllArgsConstructor
    23 public class CompareCollectionDto<T> implements Serializable {
    24     private static final long serialVersionUID = -4977550220859897197L;
    25     private String filedName;
    26     private Collection<T> oldCollection;
    27     private Collection<T> newCollection;
    28 }

    测试类:

     1 package com.tomato.boss.common;
     2 
     3 import java.util.Arrays;
     4 import java.util.List;
     5 
     6 import com.tomato.boss.common.utils.CompareCollectionDto;
     7 import com.tomato.boss.common.utils.CompareDifferenceUtil;
     8 
     9 import lombok.Getter;
    10 import lombok.Setter;
    11 
    12 public class CompareDifferenceUtilTest {
    13     public static void main(String[] args) {
    14         Dto dto1 = new Dto();
    15         Dto dto2 = new Dto();
    16         
    17         dto1.setAge(10);
    18         dto1.setDelete(false);
    19         dto1.setFlag(false);
    20         dto1.setIssTrue(false);
    21         dto1.setName("张三");
    22         dto1.setSize(10);
    23         dto1.setTrue(false);
    24         dto1.setCreateBy("xxx");
    25         dto1.setType("1");
    26         
    27         dto2.setAge(15);
    28         dto2.setDelete(true);
    29         dto2.setFlag(true);
    30         dto2.setIssTrue(true);
    31         dto2.setName("李四");
    32         dto2.setSize(20);
    33         dto2.setTrue(true);
    34         dto2.setCreateBy("yyyyy");
    35         dto2.setType("2");
    36         
    37         List<Integer> oldList = Arrays.asList(1,2,3);
    38         List<Integer> newList = Arrays.asList(2,3,4);
    39         
    40         dto1.setArr(oldList);
    41         dto2.setArr(newList);
    42         
    43         System.out.println(CompareDifferenceUtil.isDifference(dto1, dto2));
    44         System.out.println(CompareDifferenceUtil.compare(dto1, dto2));
    45         System.out.println(CompareDifferenceUtil.isDifference(oldList, newList));
    46         System.out.println(CompareDifferenceUtil.compareCollection(oldList, newList));
    47         
    48         CompareCollectionDto<Integer> dto = new CompareCollectionDto<>("arr",oldList,newList);
    49         CompareCollectionDto<Integer> dtox = new CompareCollectionDto<>("arry",oldList,newList);
    50         
    51         System.out.println(CompareDifferenceUtil.compare(dto1, dto2, dto, dtox));
    52         
    53         Children c1 = new Children();
    54         c1.setCname("张三");
    55 
    56         Children c2 = new Children();
    57         c2.setCname("李四");
    58         
    59         System.out.println(CompareDifferenceUtil.compareMainAndDetail(dto1, dto2, "child", c1, c2));
    60     }
    61     
    62     
    63     @Getter
    64     @Setter
    65     public static class Dto extends P{
    66         private boolean isTrue;
    67         private boolean issTrue;
    68         private boolean delete;
    69         private Boolean flag;
    70         private String name;
    71         private Integer age;
    72         private int size;
    73         private String createBy;
    74         private List<Integer> arr;
    75     }
    76     
    77     @Getter
    78     @Setter
    79     public static class P {
    80         private String type;
    81     }
    82     
    83     @Getter
    84     @Setter
    85     public static class Children {
    86         private String cname;
    87     }
    88 }
    
    

    测试结果比较对象的(JSON格式的字符串):

    [{
            "column": "name",
            "difference": {
                "newValue": "李四",
                "oldValue": "张三"
            }
        }, {
            "column": "delete",
            "difference": {
                "newValue": true,
                "oldValue": false
            }
        }, {
            "column": "age",
            "difference": {
                "newValue": 15,
                "oldValue": 10
            }
        }, {
            "column": "issTrue",
            "difference": {
                "newValue": true,
                "oldValue": false
            }
        }, {
            "column": "isTrue",
            "difference": {
                "newValue": true,
                "oldValue": false
            }
        }, {
            "column": "flag",
            "difference": {
                "newValue": true,
                "oldValue": false
            }
        }, {
            "column": "size",
            "difference": {
                "newValue": 20,
                "oldValue": 10
            }
        }
    ]

     比较集合的:

     1 [{
     2         "column": "delete",
     3         "difference": {
     4             "newValue": null,
     5             "oldValue": 1
     6         }
     7     }, {
     8         "column": "add",
     9         "difference": {
    10             "newValue": 4,
    11             "oldValue": null
    12         }
    13     }
    14 ]

     比较dto+集合的:

     1 [{
     2         "column": "name",
     3         "difference": {
     4             "newValue": "李四",
     5             "oldValue": "张三"
     6         }
     7     }, {
     8         "column": "arr",
     9         "difference": {
    10             "newValue": [{
    11                     "column": "delete",
    12                     "difference": {
    13                         "newValue": null,
    14                         "oldValue": [1]
    15                     }
    16                 }, {
    17                     "column": "add",
    18                     "difference": {
    19                         "newValue": [4],
    20                         "oldValue": null
    21                     }
    22                 }
    23             ],
    24             "oldValue": null
    25         }
    26     }
    27 ]

     比较dto+子dto的:

     1 [
     2     {
     3         "column": "name",
     4         "difference": {
     5             "newValue": "李四",
     6             "oldValue": "张三"
     7         }
     8     }, {
     9         "column": "delete",
    10         "difference": {
    11             "newValue": true,
    12             "oldValue": false
    13         }
    14     }, {
    15         "column": "child",
    16         "difference": {
    17             "newValue": [{
    18                     "column": "cname",
    19                     "difference": {
    20                         "newValue": "李四",
    21                         "oldValue": "张三"
    22                     }
    23                 }
    24             ],
    25             "oldValue": null
    26         }
    27     }
    28 ]
  • 相关阅读:
    OpenCV在MFC图像控件内显示图像
    Android APK反编译具体解释(附图)
    Android下用Properties保存程序配置
    王灏:光音网络致力打造Wi-Fi大生态圈
    解决ccSvcHst.exe CPU占用超50%的问题,及其缘由
    配置管理工具比較
    应用程序无法正常启动0xc0150002 解决方式
    现有一些开源ESB总线的比較
    使用GridView自带分页的代码
    Hadoop 2.4.0新特性介绍
  • 原文地址:https://www.cnblogs.com/yangzhilong/p/8085019.html
Copyright © 2020-2023  润新知