欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java如何比較兩個對象并獲取不相等的字段詳解

 更新時間:2021年11月25日 09:15:46   作者:dadiyang  
這篇文章主要給大家介紹了關于Java如何比較兩個對象并獲取不相等的字段以及JAVA判斷(獲?。﹥蓚€相同對象不同的數(shù)據(jù)的相關資料,文中通過實例代碼介紹的非常詳細,對大家學習或者使用java具有一定的參考學習價值,需要的朋友可以參考下

?寫在前面

在工作中,我們經常會遇到這樣的需求——比較兩個對象是否相等,如果不相等的話,取出不相等的字段。

以下這些場景都需要我們對一個對象進行比較:

  • 數(shù)據(jù)比對
  • 做單元測試斷言對象是否相等
  • 前端要求對不相等的字段進行高亮顯示

這種需求其實是非常簡單的,但是如何優(yōu)雅地解決這一類需求呢?

通常的做法是重寫對象的 equals 方法。但是重寫 equals 方法有很多缺點,例如:

  • 每次對象屬性有變更,一定要記得再重寫(放心,你一定會忘記的)
  • 每個對象只能有一個 equals 方法,但是可能你會需要不同的比對規(guī)則
  • 只能對比兩個對象是否相等,無法具體知道哪個屬性不等
  • 自動生成的 equals 方法無法基于 getter 方法進行比對
  • 對象來自第三方依賴,無法重寫 equals 方法

因此,實現(xiàn)一個通用的比對器可以減少很多不必要的麻煩,幫助我們很好地完成這一類的需求。

緣起

我是在做數(shù)據(jù)同步的時候有這個需求,我要將數(shù)據(jù)庫的數(shù)據(jù)通過一定的規(guī)則導入到 ES 中,導入完成之后,如何比對兩邊的數(shù)據(jù)是否一致呢?這時候一個好用的比對器就是我非常好的幫手。

另外,我在做單元測試的時候發(fā)現(xiàn),經常會需要將被測方法的返回值和期望的結果做 assertEquals 斷言這時這個比對器也非常有幫助。我發(fā)現(xiàn)很多同事經常會遇到類似的需求。

于是,我找時間自己實現(xiàn)了一下。

實現(xiàn)

使用反射對傳入的對象進行比對,提供了基于字段的比較器和基于 Getter 方法的對比器,并且充分考慮擴展性,使用者可以重寫字段的比對規(guī)則。功能相對簡單,代碼實現(xiàn)也不難,而且做了很多注釋,具體實現(xiàn)可以直接查看源碼。

項目地址:https://github.com/dadiyang/equator

UML圖:

使用方法

因為已經上傳到了 maven 倉庫中,我們使用非常方便:

添加 maven 依賴

<dependency>
    <groupId>com.github.dadiyang</groupId>
    <artifactId>equator</artifactId>
    <version>1.0.3</version>
</dependency>

初始化并調用方法

Equator equator = new GetterBaseEquator();
User user1 = new User(...);
User user2 = new User(...);
// 判斷屬性是否完全相等
equator.isEquals(user1, user2);
// 獲取不同的屬性
List<FieldInfo> diff = equator.getDiffFields(user1, user2);

擴展

我們可以通過繼承并重寫 isFieldEquals 方法自定義比對規(guī)則,例如我們在做單元測試的時候,對于 Date 類型的字段的比對,通常數(shù)據(jù)庫不保存毫秒數(shù),而我們 new 出來的 Date 對象則包含了毫秒數(shù),因此我們在對包含 Date 類型字段的對象做比對的時候需要忽略日期的毫秒數(shù)。這時就可以通過重寫isFieldEquals 方法來自定義了:

/**
 * 日期在數(shù)據(jù)庫不保存毫秒數(shù),因此需要特殊處理,比對時間時,忽略毫秒數(shù)
 *
 * @author dadiyang
 * @date 2019/3/23
 */
public class MmInsensitiveEquator extends GetterBaseEquator {
    @Override
    protected boolean isFieldEquals(FieldInfo fieldInfo) {
        if (fieldInfo.getFirstVal() instanceof Date) {
            Date first = (Date) fieldInfo.getFirstVal();
            Date second = (Date) fieldInfo.getSecondVal();
            if (Objects.equals(first, second)) {
                return true;
            }
            // 忽略毫秒數(shù)
            return Objects.equals(Math.round(first.getTime() / 1000), Math.round(second.getTime() / 1000));
        }
        return super.isFieldEquals(fieldInfo);
    }
}

后記

對象比對是一個非常小的需求,通常我們只會寫一個工具類來完成。但是寫一個工具類在各個項目間隨處拷貝,非常不優(yōu)雅,給整個團隊帶來很多不必要的維護成本。而且擴展性比較差,有任何差異就需要寫很多代碼去實現(xiàn)。

這時,如果我們從具體解決某一個需求的視角上升到解決一類需求,那么就能想出更加通用和優(yōu)雅的解決方案了。一個個具體的需求是無窮無盡的,以有限的人生去解決無限的需求,殆矣;但是將它們歸類之后,我們會發(fā)現(xiàn),需求的種類是有限的。

附:JAVA判斷(獲取)兩個相同對象不同的數(shù)據(jù)

項目中需要獲取修改前和修改后的不同數(shù)據(jù)并進行保存。

不知道高大上的做法,就寫個工具類。

package com.shiyan.utils.object;
 
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
 
import org.apache.commons.lang3.StringUtils;
 
public class GetDifference {
 
	public static Map<String, String> getUser(Object a, Object b)
			throws IllegalArgumentException, IllegalAccessException {
		Map<String, String> map = new HashMap<String, String>();
		Field[] declaredFields2 = a.getClass().getDeclaredFields();
		Field[] declaredFields23 = b.getClass().getDeclaredFields();
		StringBuilder xiugaiqian = new StringBuilder();
		StringBuffer xiugaihou = new StringBuffer();
		for (int i = 0; i < declaredFields2.length; i++) {
			declaredFields2[i].setAccessible(true);
			declaredFields23[i].setAccessible(true);
			if (declaredFields2[i].get(a) != null && declaredFields23[i].get(b) != null) {
 
				if (!declaredFields2[i].get(a).equals(declaredFields23[i].get(b))) {
					xiugaiqian.append(declaredFields2[i].getName() + ":" + declaredFields2[i].get(a)).append(",");
					xiugaihou.append(declaredFields23[i].getName() + ":" + declaredFields23[i].get(b)).append(",");
				}
			} else if (declaredFields2[i].get(a) == null && declaredFields23[i].get(b) != null) {
				xiugaiqian.append(declaredFields2[i].getName() + ":" + null).append(",");
				xiugaihou.append(declaredFields23[i].getName() + ":" + declaredFields23[i].get(b)).append(",");
			} else if (declaredFields2[i].get(a) != null && declaredFields23[i].get(b) == null) {
				xiugaiqian.append(declaredFields2[i].getName() + ":" + declaredFields2[i].get(a)).append(",");
				xiugaihou.append(declaredFields23[i].getName() + ":" + null).append(",");
			}
		}
 
		if (StringUtils.isNoneBlank(xiugaiqian.toString()) && StringUtils.isNoneBlank(xiugaihou.toString())) {
			map.put(xiugaiqian.toString().substring(0, xiugaiqian.length() - 1),
					xiugaihou.toString().substring(0, xiugaihou.length() - 1));
		}
		return map;
 
	}
}

測試代碼

/**
 * 
 * Description:   
 * @Author:xieyuxin 
 * @param 
 * @param 設定文件   
 * @throws 
 * @return String    
 * @Exception 異常對象
 */
package com.shiyan.test;
 
import java.util.Map;
import com.shiyan.utils.object.GetDifference;
 
 
public class ObjectGetEerro {
 
	public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
		Persion p1 = new Persion.Builder().age(12).name("張三").t("2018-10-20").build();
		Persion p2 = new Persion.Builder().age(16).name("1111").build();
		Map<String, String> user = GetDifference.getUser(p1, p2);
		for(Map.Entry<String, String> entry : user.entrySet()){
			 System.out.println("修改前 :" + entry.getKey());
			 System.out.println("修改后 :" + entry.getValue());
		}
	}
 
}

到此這篇關于Java如何比較兩個對象并獲取不相等字段的文章就介紹到這了,更多相關Java比較兩個對象內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java雪花算法的原理和實現(xiàn)方法

    Java雪花算法的原理和實現(xiàn)方法

    這篇文章主要介紹了Java雪花算法的原理和實現(xiàn)方法,雪花算法是一種分布式唯一ID生成算法,可以生成全局唯一的ID標識符,就像自然界中雪花一般沒有相同的雪花,下面將詳細介紹,感興趣的可以學習一下
    2023-10-10
  • Spring Boot整合Thymeleaf詳解

    Spring Boot整合Thymeleaf詳解

    這篇文章主要介紹了Spring Boot整合Thymeleaf詳解,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-08-08
  • Spring中的@ResponseStatus使用

    Spring中的@ResponseStatus使用

    這篇文章主要介紹了Spring中的@ResponseStatus使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • Java定時任務Timer、TimerTask與ScheduledThreadPoolExecutor詳解

    Java定時任務Timer、TimerTask與ScheduledThreadPoolExecutor詳解

    這篇文章主要介紹了Java定時任務Timer、TimerTask與ScheduledThreadPoolExecutor詳解,  定時任務就是在指定時間執(zhí)行程序,或周期性執(zhí)行計劃任務,Java中實現(xiàn)定時任務的方法有很多,本文從從JDK自帶的一些方法來實現(xiàn)定時任務的需求,需要的朋友可以參考下
    2024-01-01
  • 使用spring.profiles.active來分區(qū)配置的方法示例

    使用spring.profiles.active來分區(qū)配置的方法示例

    這篇文章主要介紹了使用spring.profiles.active來分區(qū)配置的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-01-01
  • Java 根據(jù)網絡URL獲取該網頁上面所有的img標簽并下載圖片

    Java 根據(jù)網絡URL獲取該網頁上面所有的img標簽并下載圖片

    這篇文章主要介紹了Java 根據(jù)網絡URL獲取該網頁上面所有的img標簽并下載圖片,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-11-11
  • Java實現(xiàn)刪除排序數(shù)組中重復元素的方法小結【三種方法比較】

    Java實現(xiàn)刪除排序數(shù)組中重復元素的方法小結【三種方法比較】

    這篇文章主要介紹了Java實現(xiàn)刪除排序數(shù)組中重復元素的方法,結合實例形式對比分析了三種常見的數(shù)組元素刪除算法操作技巧,需要的朋友可以參考下
    2019-02-02
  • Java如何設置PDF文檔背景色詳解

    Java如何設置PDF文檔背景色詳解

    這篇文章主要介紹了Java如何設置PDF文檔背景色詳解,一般生成的PDF文檔默認的文檔底色為白色,我們可以通過一定方法來更改文檔的背景色,以達到文檔美化以及保護雙眼的作用。 以下內容提供了Java編程來設置PDF背景色的方法,需要的朋友可以參考下
    2019-07-07
  • Java實現(xiàn)PDF導出功能的示例代碼

    Java實現(xiàn)PDF導出功能的示例代碼

    這篇文章主要為大家詳細介紹了Java實現(xiàn)PDF導出功能的相關知識,文中的示例代碼講解詳細,具有一定的學習價值,感興趣的小伙伴可以了解下
    2023-09-09
  • Java try()語句實現(xiàn)try-with-resources異常管理機制操作

    Java try()語句實現(xiàn)try-with-resources異常管理機制操作

    這篇文章主要介紹了Java try()語句實現(xiàn)try-with-resources異常管理機制操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09

最新評論