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. pandas常用方法之read_excel详解

    前期准备 准备测试数据如下: fl_path = r"C:\Users\Desktop\test.xlsx" dic = { 'num': ['001', '002', '003' ...

  2. mybati之sql集合

    mybatis 详解(五)------动态SQL - YSOcean - 博客园 (cnblogs.com) mybatis参数注入: 根据参数名称 使用#{} 注入参数 <insert id= ...

  3. Unity异步加载场景与加载进度条

    先上效果图 需要三个场景 1,2, 3 从场景1跳转到场景3,场景2是加载场景 场景1按钮的代码如下 using System.Collections; using System.Collection ...

  4. docker从C盘迁移到D盘

    docker镜像在C盘占据大量的空间,将.docker从C:\Users\Administrator迁移到E:\.docker. 一.关闭virtual Box 使virtual Box处于关闭.停止 ...

  5. js apply 与 call

    简介 用来调用方法,第一个参数替换掉用方法的this对象 区别:call:A.fn.call(B, arg1,arg2,argn...),后面的参数用逗号分隔 apply:A.fn.apply(B, ...

  6. CCF 202006-2 稀疏向量

    #include <iostream> #include <bits/stdc++.h> #include <string> using namespace std ...

  7. 2021/9/26 Leetcode 两数之和

    题目:给你两个整数 a 和 b ,不使用 运算符 + 和 - ​​​​​​​,计算并返回两整数之和. int getSum(int a, int b) { while(b != 0){ unsigne ...

  8. ssh scp 相关

    1. 设置ssh 的免密登录 1> 将 ~/.ssh/id_rsa.pub文件中的内容拷贝到 远程host的 ~/.ssh/authorized_keys文件中 2> ssh-copy-i ...

  9. LeetCode系列之 (JavaScript) => 66. 加一

    题目描述: 解题思路分析: 模拟十进制: 分析有几种情况,按情况来定 不同解法: /** * @param {number[]} digits * @return {number[]} */ // v ...

  10. 一个线程池的c++实现

    前面我们实现了CallBack类,实现了对任意可调用对象的封装,且统一了调用接口. 现在利用CallBack类,我们来实现一个线程池,我们的线程池包含: 1. 状态机, 用于控制和管理线程池的运行.停 ...