声明:本文属原创文章,始发于 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); } }
对象比对是一个很是小的需求,一般咱们只会写一个工具类来完成。可是写一个工具类在各个项目间随处拷贝,很是不优雅,给整个团队带来不少没必要要的维护成本。并且扩展性比较差,有任何差别就须要写不少代码去实现。
这时,若是咱们从具体解决某一个需求的视角上升到解决一类需求,那么就能想出更加通用和优雅的解决方案了。一个个具体的需求是无穷无尽的,以有限的人生去解决无限的需求,殆矣;可是将它们归类以后,咱们会发现,需求的种类是有限的。
所以解决一类一类问题,能让咱们摆脱无穷无尽的重复劳动,少加点班,多点时间陪陪家人哦。