Java 比较两个对象的不同之处(old, new) 包含 bean 对象下的 list, Map , bean 的细节
package com.icil.pinpal.test1; import com.alibaba.fastjson.JSONObject; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.junit.Test; import org.springframework.util.Assert; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; import java.util.stream.Collectors; /*************************** *<pre> * @Project Name : base-case-test-service * @Package : com.icil.pinpal.test1 * @File Name : BaseTest * @Author : Sea * @Mail : lshan523@163.com * @Date : 2022/11/21 16:43 * @Purpose : * @History : *</pre> ***************************/ public class BaseTest { // ########################## 准备bean ############################## /* @AllArgsConstructor @NoArgsConstructor @Data static public class BaseDO { private String name; private Integer age; private List<String> likes; private List<Child> childrens; private Map mymap; private Child childx; public BaseDO(String name, Integer age, List<String> likes, List<Child> childrens) { this.name = name; this.age = age; this.likes = likes; this.childrens = childrens; } } @AllArgsConstructor @NoArgsConstructor @Data static public class Child { private String name; private Integer age; }*/ // ########################## 比较 方法 ############################## private static final List<Class<?>> WRAPPER = Arrays.asList(Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Character.class, Boolean.class, String.class); /** * compare the bean fields value if different * @param source obj * @param target obj * @return {key:[old,new]} * @throws Exception */ public static JSONObject getDiff(Object source, Object target) throws Exception { JSONObject diff =new JSONObject(); Assert.notNull(source, "Source must not be null"); Assert.notNull(target, "Target must not be null"); Class<?> compareObj = target.getClass(); Field[] fields = compareObj.getDeclaredFields(); for (Field field : fields) { PropertyDescriptor pd = new PropertyDescriptor(field.getName(), compareObj); Method getMethod = pd.getReadMethod(); Object o1 = getMethod.invoke(source); Object o2 = getMethod.invoke(target); String s1 = o1 == null ? "" : o1.toString(); String s2 = o2 == null ? "" : o2.toString(); if (!s1.equals(s2)) { //############### 处理list,对比list 的不同 ################## if(o1 instanceof Collection){ Collection<Object> o11 = (Collection) o1; Collection<Object> o22 = (Collection) o2; Collection common = o11.stream().filter(o -> o22.contains(o)).collect(Collectors.toList()); o11.removeAll(common); o22.removeAll(common); diff.put(field.getName(), Arrays.asList(o11,o22)); } else if(o1 instanceof Map) { // ######### 处理 map 对比map 的不同 ######### Map<String,Object> O11 = (Map) o1; Map<String,Object> O22 = (Map) o2; // o1 diff 02 JSONObject o1diffo2 = new JSONObject(); for(Map.Entry<String,Object> oo1 : O11.entrySet()) { String key = oo1.getKey(); O11.getOrDefault(key,""); if(!O11.getOrDefault(key,"").equals(O22.getOrDefault(key,""))){ o1diffo2.put(key,oo1.getValue()); } } // o2 diff 01 JSONObject o2diffo1 = new JSONObject(); for(Map.Entry<String,Object> oo2 : O22.entrySet()) { String key = oo2.getKey(); O11.getOrDefault(key,""); if(!O22.getOrDefault(key,"").equals(O11.getOrDefault(key,""))){ o1diffo1.put(key,oo2.getValue()); } } diff.put(field.getName(), Arrays.asList(o1diffo2,o2diffo1)); } // ################## 如果为 bean 对象 (不是基本类型,不是list 也不是map) ################## else if((!o1.getClass().isPrimitive() && !WRAPPER.contains(o1.getClass())) && !(o1 instanceof Collection) && !(o1 instanceof Map)) { diff.put(field.getName(), getDiff(o1,o2)); } else { diff.put(field.getName(), Arrays.asList(s1,s2)); } }; } return diff; } @Test public void testNam1e() throws Exception { // 数据一 List<String> likes = new ArrayList<String>(){ {add("basketball"); add("football");} }; List<Child> childrens = new ArrayList<Child>(){{ add(new Child("aa",12)); add(new Child("bb",15)); }}; BaseDO sea = new BaseDO("sea", 30, likes, childrens); sea.setMymap(new HashMap() {{put("xx22","1"); put("xx1","2"); put("xx2","12"); put("xxxx2","12");}}); sea.setChildx(new Child("xx",12)); // 数据二 List<String> likes1 = new ArrayList<String>(){ {add("Table tennis"); add("football");} }; List<Child> childrens1 = new ArrayList<Child>(){{ add(new Child("aa",12)); add(new Child("cc",12)); add(new Child("bb",16)); }}; BaseDO sea1 = new BaseDO("sea", 31, likes1, childrens1); sea1.setMymap(new HashMap() {{put("xx","1"); put("xx1","2"); put("xx2","12");}}); sea1.setChildx(new Child("xxx",12)); //比较 JSONObject diff = getDiff(sea, sea1); System.err.println(diff); } }
测试结果:
{"childrens":[[{"age":15,"name":"bb"}],[{"age":12,"name":"cc"},{"age":16,"name":"bb"}]],"childx":{"name":["xx","xxx"]},"mymap":[{"xxxx2":"12","xx22":"1"},{"xx":"1"}],"age":["30","31"],"likes":[["basketball"],["Table tennis"]]}