最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java如何比較兩個(gè)對(duì)象并獲取不相等的字段詳解

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

?寫在前面

在工作中,我們經(jīng)常會(huì)遇到這樣的需求——比較兩個(gè)對(duì)象是否相等,如果不相等的話,取出不相等的字段。

以下這些場(chǎng)景都需要我們對(duì)一個(gè)對(duì)象進(jìn)行比較:

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

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

通常的做法是重寫對(duì)象的 equals 方法。但是重寫 equals 方法有很多缺點(diǎn),例如:

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

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

緣起

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

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

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

實(shí)現(xiàn)

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

項(xiàng)目地址:https://github.com/dadiyang/equator

UML圖:

使用方法

因?yàn)橐呀?jīng)上傳到了 maven 倉(cāng)庫(kù)中,我們使用非常方便:

添加 maven 依賴

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

初始化并調(diào)用方法

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

擴(kuò)展

我們可以通過(guò)繼承并重寫 isFieldEquals 方法自定義比對(duì)規(guī)則,例如我們?cè)谧鰡卧獪y(cè)試的時(shí)候,對(duì)于 Date 類型的字段的比對(duì),通常數(shù)據(jù)庫(kù)不保存毫秒數(shù),而我們 new 出來(lái)的 Date 對(duì)象則包含了毫秒數(shù),因此我們?cè)趯?duì)包含 Date 類型字段的對(duì)象做比對(duì)的時(shí)候需要忽略日期的毫秒數(shù)。這時(shí)就可以通過(guò)重寫isFieldEquals 方法來(lái)自定義了:

/**
 * 日期在數(shù)據(jù)庫(kù)不保存毫秒數(shù),因此需要特殊處理,比對(duì)時(shí)間時(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);
    }
}

后記

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

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

附:JAVA判斷(獲?。﹥蓚€(gè)相同對(duì)象不同的數(shù)據(jù)

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

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

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;
 
	}
}

測(cè)試代碼

/**
 * 
 * Description:   
 * @Author:xieyuxin 
 * @param 
 * @param 設(shè)定文件   
 * @throws 
 * @return String    
 * @Exception 異常對(duì)象
 */
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());
		}
	}
 
}

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

相關(guān)文章

  • java判斷class子類或父類的實(shí)例方法

    java判斷class子類或父類的實(shí)例方法

    在本篇文章里小編給大家整理的是關(guān)于java判斷class子類或父類的實(shí)例方法,需要的朋友們可以參考學(xué)習(xí)下。
    2020-02-02
  • Java 處理圖片與base64 編碼的相互轉(zhuǎn)換的示例

    Java 處理圖片與base64 編碼的相互轉(zhuǎn)換的示例

    本篇文章主要介紹了Java 處理圖片與base64 編碼的相互轉(zhuǎn)換的示例,具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-08-08
  • 詳解Http協(xié)議以及post與get區(qū)別

    詳解Http協(xié)議以及post與get區(qū)別

    這篇文章主要介紹了詳解Http協(xié)議以及post與get區(qū)別,通過(guò)分別說(shuō)明Http協(xié)議以及get與post各自的概念,再到兩者作比較有著詳細(xì)的說(shuō)明,希望對(duì)你有所幫助
    2021-06-06
  • 關(guān)于Java實(shí)現(xiàn)word(docx、doc)轉(zhuǎn)html的完美解決方案

    關(guān)于Java實(shí)現(xiàn)word(docx、doc)轉(zhuǎn)html的完美解決方案

    文章介紹了多種將Word文檔轉(zhuǎn)換為HTML的方法,包括使用Microsoft Word自帶的導(dǎo)出功能、第三方工具和編程實(shí)現(xiàn),展示了如何實(shí)現(xiàn)將.docx文件轉(zhuǎn)換為HTML文件,并自動(dòng)生成目錄、處理分頁(yè)符和增強(qiáng)表格樣式等功能,感興趣的朋友一起看看吧
    2025-01-01
  • Spring aop+反射實(shí)現(xiàn)電話號(hào)加密

    Spring aop+反射實(shí)現(xiàn)電話號(hào)加密

    線上項(xiàng)目涉及大量查詢接口中,存在電話號(hào)明文展示不合規(guī)的問(wèn)題。如果對(duì)每個(gè)接口返回結(jié)果中電話號(hào)相關(guān)字段修改相關(guān)代碼邏輯,則工作量較大花費(fèi)時(shí)間多。因此設(shè)計(jì)電話號(hào)加密注解,減少工作量。
    2021-06-06
  • Spring注解@Resource和@Autowired區(qū)別對(duì)比詳解

    Spring注解@Resource和@Autowired區(qū)別對(duì)比詳解

    這篇文章主要介紹了Spring注解@Resource和@Autowired區(qū)別對(duì)比詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • Java實(shí)現(xiàn)MySQL數(shù)據(jù)實(shí)時(shí)同步至Elasticsearch的方法詳解

    Java實(shí)現(xiàn)MySQL數(shù)據(jù)實(shí)時(shí)同步至Elasticsearch的方法詳解

    MySQL擅長(zhǎng)事務(wù)處理,而Elasticsearch(ES)則專注于搜索與分析,將MySQL數(shù)據(jù)實(shí)時(shí)同步到ES,可以充分發(fā)揮兩者的優(yōu)勢(shì),下面我們就來(lái)看看如何使用Java實(shí)現(xiàn)這一功能吧
    2025-03-03
  • rabbitmq中routingkey的作用說(shuō)明

    rabbitmq中routingkey的作用說(shuō)明

    這篇文章主要介紹了rabbitmq中routingkey的作用說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • 基于Spring的RPC通訊模型的使用與比較

    基于Spring的RPC通訊模型的使用與比較

    這篇文章主要介紹了基于Spring的RPC通訊模型的使用與比較,詳細(xì)的介紹了RMI、Caucho的Hessian和Burlap以及Spring自帶的HTTP invoker,感興趣的可以了解一下
    2018-09-09
  • SpringBoot @Autowired注解注入規(guī)則介紹

    SpringBoot @Autowired注解注入規(guī)則介紹

    這篇文章主要介紹了SpringBoot @Autowired注解注入規(guī)則介紹,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。
    2021-11-11

最新評(píng)論

临朐县| 辛集市| 竹北市| 梅河口市| 黄骅市| 通河县| 吴忠市| 孝感市| 澄迈县| 永福县| 宣恩县| 长宁区| 同德县| 龙州县| 安徽省| 娄烦县| 城口县| 雷波县| 天镇县| 五河县| 牡丹江市| 曲水县| 阳泉市| 宝山区| 上虞市| 大渡口区| 彭泽县| 湖北省| 叙永县| 布拖县| 莱芜市| 治县。| 台北县| 桂平市| 中方县| 哈密市| 元阳县| 广宗县| 大关县| 会宁县| 罗江县|