java 比较两个实体对象的值差异

本文介绍了一个Java工具类,用于比较两个对象的特定属性值,支持忽略和记录原始值差异。它通过反射机制处理不同实体对象,适用于检查数据更新或校验前后状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.beanutils.PropertyUtils;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.util.*;

/**
 * 比较对象属性是否发生变化
 */
public class CompareFieldUtils {

    /**
     * 比较两个不同实体属性值
     * @param sourceObj 原对象
     * @param currentObj 当前对象
     * @param compareArr 需要比较的字段
     * @return
     */
    public static Map<String, Object> compareFields(Object sourceObj, Object currentObj, String[] compareArr, String[] ignoreArr) {
        try{
            Map<String, Object> map = new HashMap<String, Object>();
            Map<String, Object> oldValueMap = new HashMap<String, Object>();
            List<String> compareList = (compareArr == null || compareArr.length == 0)?null:Arrays.asList(compareArr);
            List<String> ignoreList =  (ignoreArr == null || ignoreArr.length == 0)?null:Arrays.asList(ignoreArr);
            Class clazz = sourceObj.getClass();
            Class clazz_current = currentObj.getClass();
            // 获取object的属性描述
            PropertyDescriptor[] pds = Introspector.getBeanInfo(clazz, Object.class).getPropertyDescriptors();
            BeanInfo current_bean = Introspector.getBeanInfo(clazz_current, Object.class);
            for (PropertyDescriptor pd : pds) {// 这里就是所有的属性了
                String name = pd.getName();// 属性名
                //比较字段不为空,且当前字段不在比较的范围内
                if(compareList != null && !compareList.contains(name)){
                    continue;
                }
                //忽略字段不为空,且当前字段在忽略的范围内

                if(ignoreList != null && ignoreList.contains(name)){
                    continue;
                }
                Method readMethod = pd.getReadMethod();// get方法
                // 在sourceObj上调用get方法等同于获得sourceObj的属性值
                Object o1 = readMethod.invoke(sourceObj);
                // 在currentObj上调用get方法等同于获得currentObj的属性值
                Method readMethod_current = clazz_current.getMethod("get"+ name.substring(0,1).toUpperCase() + name.substring(1));
                Object o2 = readMethod_current.invoke(currentObj);
                if(o1 instanceof Timestamp){
                    o1 = new Date(((Timestamp) o1).getTime());
                }
                if(o2 instanceof Timestamp){
                    o2 = new Date(((Timestamp) o2).getTime());
                }
                if(o1 == null && o2 == null){
                    continue;
                }else if(o1 == null && o2 != null){
                    map.put(name, o2);
                    oldValueMap.put(name, 01);
                    continue;
                }
                if (!o1.equals(o2)) {// 比较这两个值是否相等,不等就可以放入map
                    map.put(name, o2);
                    oldValueMap.put(name, 01);
                }
            }
            //将原始值记录起来,方便可查看差异,可按需去掉
            if(!oldValueMap.isEmpty()) {
                map.put("oldValueMap", JSONObject.toJSONString(oldValueMap));
            }
            return map;
        }catch(Exception e){
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 按指定的属性列表赋值对象
     *
     * @param source 原数据对象
     * @param target 目标对象
     * @param changeMap
     *
     */
    public static void copyWithProperties(Object source, Object target, Map<String, Object> changeMap) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        for (String property : changeMap.keySet()) {
            PropertyUtils.setProperty(target, property, PropertyUtils.getProperty(source, property));
        }
    }

}

Java中,比较两个实体对象中相同属性名的是否相同通常需要遍历这两个对象的属性并逐一进行比较。假设我们有两个类Person,它们都有姓名(name)这个属性,你可以这样做: ```java public class Person { private String name; // getters and setters... } // 比较两个Person对象的name属性 public boolean comparePersons(Person person1, Person person2) { if (person1 == null || person2 == null) { return false; // 如果其中一个对象为null,则认为它们不相等 } return person1.getName().equals(person2.getName()); } ``` 上述`comparePersons`方法会检查person1和person2的name属性是否相等,如果相等则返回true,否则返回false。 如果你想要一个通用的方法来处理任意两个具有相同属性的对象,并返回一个布尔表示它们是否完全相同(所有属性都相同),你可以创建一个递归版本的比较函数,递归地遍历每个实体的所有属性。 ```java public boolean compareObjects(Object obj1, Object obj2, Map<String, Method> methods) { // ...省略一些基本情况判断... if (obj1.getClass() != obj2.getClass()) { return false; } // 获取当前类的所有公共方法 List<Method> declaredMethods = obj1.getClass().getDeclaredMethods(); for (Method method : declaredMethods) { if (methods.containsKey(method.getName())) { // 如果方法已处理过,跳过 continue; } try { // 调用方法并获取结果 Object result1 = method.invoke(obj1); Object result2 = method.invoke(obj2); // 对结果继续递归比较 if (!compareObjects(result1, result2, methods)) { return false; } } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { throw new RuntimeException("Error comparing objects", e); } } // 所有方法都比较过了,没有发现差异,说明它们相同 return true; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值