一个自己写的判断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 ]
原文地址:https://www.cnblogs.com/yangzhilong/p/8085019.html