聲明:本文屬原創文章,始發於 https://blog.csdn.net/dadiyan...。特此,同步發佈到 sf,轉載請註明出處。前端
在工做中,咱們常常會遇到這樣的需求——比較兩個對象是否相等,若是不相等的話,取出不相等的字段。java
如下這些場景都須要咱們對一個對象進行比較:git
這種需求實際上是很是簡單的,可是如何優雅地解決這一類需求呢?github
一般的作法是重寫對象的 equals
方法。可是重寫 equals
方法有不少缺點,例如:數據庫
equals
方法,可是可能你會須要不一樣的比對規則 equals
方法沒法基於 getter
方法進行比對equals
方法所以,實現一個通用的比對器能夠減小不少沒必要要的麻煩,幫助咱們很好地完成這一類的需求。maven
我是在作數據同步的時候有這個需求,我要將數據庫的數據經過必定的規則導入到 ES 中,導入完成以後,如何比對兩邊的數據是否一致呢?這時候一個好用的比對器就是我很是好的幫手。ide
另外,我在作單元測試的時候發現,常常會須要將被測方法的返回值和指望的結果作 assertEquals
斷言這時這個比對器也很是有幫助。我發現不少同事常常會遇到相似的需求。工具
因而,我找時間本身實現了一下。單元測試
使用反射對傳入的對象進行比對,提供了基於字段的比較器和基於 Getter 方法的對比器,而且充分考慮擴展性,使用者能夠重寫字段的比對規則。功能相對簡單,代碼實現也不難,並且作了不少註釋,具體實現能夠直接查看源碼。測試
項目地址:https://github.com/dadiyang/e...
UML圖:
由於已經上傳到了 maven 倉庫中,咱們使用很是方便:
<dependency> <groupId>com.github.dadiyang</groupId> <artifactId>equator</artifactId> <version>1.0.1</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
方法自定義比對規則,例如咱們在作單元測試的時候,對於 Date 類型的字段的比對,一般數據庫不保存毫秒數,而咱們 new 出來的 Date 對象則包含了毫秒數,所以咱們在對包含 Date 類型字段的對象作比對的時候須要忽略日期的毫秒數。這時就能夠經過重寫isFieldEquals
方法來自定義了:
/** * 日期在數據庫不保存毫秒數,所以須要特殊處理,比對時間時,忽略毫秒數 * * @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; } // 忽略毫秒數 return Objects.equals(Math.round(first.getTime() / 1000), Math.round(second.getTime() / 1000)); } return super.isFieldEquals(fieldInfo); } }
對象比對是一個很是小的需求,一般咱們只會寫一個工具類來完成。可是寫一個工具類在各個項目間隨處拷貝,很是不優雅,給整個團隊帶來不少沒必要要的維護成本。並且擴展性比較差,有任何差別就須要寫不少代碼去實現。
這時,若是咱們從具體解決某一個需求的視角上升到解決一類需求,那麼就能想出更加通用和優雅的解決方案了。一個個具體的需求是無窮無盡的,以有限的人生去解決無限的需求,殆矣;可是將它們歸類以後,咱們會發現,需求的種類是有限的。
所以解決一類一類問題,能讓咱們擺脫無窮無盡的重複勞動,少加點班,多點時間陪陪家人哦。