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"]]}

Java 比较两个对象的不同之处(old, new) 包含 bean 对象下的 list, Map , bean 的细节的更多相关文章

  1. java比较两个对象是否相等的方法

    java比较两个对象是否相等直接使用equals方法进行判断肯定是不会相同的. 例如: Person  person1  =new Person("张三"); Person  pe ...

  2. java中两个对象间的属性值复制,比较,转为map方法实现

    package com.franson.study.util; import java.lang.reflect.InvocationTargetException; import java.lang ...

  3. Java 判断两个对象是否相等

    一.使用 == 与 equals == : 它的作用是判断两个对象的地址是不是相等.即,判断两个对象是不是同一个对象.(基本数据类型==比较的是值,引用数据类型==比较的是内存地址) equals() ...

  4. java使double保留两位小数的多方法 java保留两位小数

    这篇文章主要介绍了java使double类型保留两位小数的方法,大家参考使用吧 复制代码 代码如下: mport java.text.DecimalFormat; DecimalFormat    d ...

  5. java保留两位小数

    java保留两位小数问题: 方式一: 四舍五入  double   f   =   111231.5585;  BigDecimal   b   =   new   BigDecimal(f);  d ...

  6. [原创]java WEB学习笔记59:Struts2学习之路---OGNL,值栈,读取对象栈中的对象的属性,读取 Context Map 里的对象的属性,调用字段和方法,数组,list,map

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  7. java中两种类型变量

    Java中有两种类型的变量,一种是对象类型,另一种是基础类型(primitive type). 对象类型普遍采用引用的方式,比如 List a = new ArrayList(); List b = ...

  8. Java 交换两个变量的数值

    一.参数传递方法 为解决标题问题,首先介绍参数传递方法.目前各类程序设计语言的参数传递方法主要有三种: 按值传递 按引用传递 按指针传递 其中按值传递表示方法(函数)接收的是调用者提供的变量的拷贝,不 ...

  9. Java中两种实现多线程方式的对比分析

    本文转载自:http://www.linuxidc.com/Linux/2013-12/93690.htm#0-tsina-1-14812-397232819ff9a47a7b7e80a40613cf ...

  10. JAVA之旅(四)——面向对象思想,成员/局部变量,匿名对象,封装 , private,构造方法,构造代码块

    JAVA之旅(四)--面向对象思想,成员/局部变量,匿名对象,封装 , private,构造方法,构造代码块 加油吧,节奏得快点了 1.概述 上篇幅也是讲了这点,这篇幅就着重的讲一下思想和案例 就拿买 ...

随机推荐

  1. mqtt安装和使用

    linux下 下载: wget https://www.emqx.io/downloads/broker/v3.2.1/emqx-centos7-v3.2.1.zip 解压:unzip emqx-ce ...

  2. C#新语法

    C#新语法 NET6新特性以及C#新语法 1.顶级语句(C#9.0) (1):直接在C#文件中直接编写入口方法的代码,不用类,不用Main.经典写法仍然支持,反编译可以查看到,编译器依旧为我们生成了一 ...

  3. uni-app 下载文件 预览 + 保存自定义目录

    作为使用uni-app的小白来说  尝试了好几种方法 终于得到了我想要的效果(如下) 1.点击下载按钮(文件 或者图片)  2.预览 :用户自定义选择查看的软件(图片在手机相册 文件用其他打开预览) ...

  4. K8S kubectl命令

    一.kubectl命令 1. 格式:kubectl [command] [type] [name] [flag] command:资源执行的操作,如create.get.delete: type:指定 ...

  5. python import导入失败 相对路径 绝对路径

    首先我们有这样一个目录结构 经过我无数次的调试,我发现从test3调用spider以及downloadss文件可以直接import调用 但是从外部的app.py文件调用,spider.py文件死活调用 ...

  6. Jmeter完整全套接口流程

    根据实际项目,编写一套完整的接口流程 项目流程介绍: 借款流程需要调用的接口,依次为: 前置校验:主要通过手机号验证该用户是存量用户,若撞库,则不允许继续操作: 用户注册:通过手机号+身份证号进行注册 ...

  7. 1.2 C语言--函数与数组

    函数 函数的定义 返回值类型函数名(类型形参名[,--]){ 函数体 } 除了没有访问修饰符外,基本等同于java的函数. 良好的程序设计风格要求即使没有返回值,也要使用return;作为最后一条语句 ...

  8. shell相关基础面试题

    用sed修改test.txt的23行test为tset: sed –i '23s/test/tset/g' test.txt 查看/web.log第25行第三列的内容. sed –n '25p' /w ...

  9. Nexus5安装PostmarketOS(Alpine Linux)并装上Docker

    ​ Postmarket OS是一个基于Alpine Linux.能够安装到手机或其他移动设备上.当然linux deploy也可以使用SSH,但linux deploy运行在容器里.使用上会有些限制 ...

  10. 音速启动 Vstart 5.7 win10手动移除后台设置主页

    Vstart 用了快12年了,用Wireshark跟踪确实会访问广告页面,也会去上传数据.还会悄悄设置主页 ,所以在Win10上老是被干掉 也想着换 CLaunch 确实不喜欢. Rolan 买了一年 ...