几个结论:
- 如果两个对象equals()相同,那么它们的hashCode()值一定要相同;
- 如果两个对象的hashCode()相同,它们的equals()并不一定相同;
- 如果重写了类中的equals方法,那么必须重写hashCode方法,否则会导致使用hash数据结构的数据失效(eg:HashMap,HashSet,HashTable…)
重写equals()需要遵循的规则:
- 对称性:如果x.equals(y)返回是 true,那么y.equals(x)也应该返回是true。
- 反射性:x.equals(x)必须返回是true。
- 类推性:如果x.equals(y)返回是true,而且y.equals(z)返回是true,那么z.equals(x)也应该返回是true。
- 一致性:如果x.equals(y)返回是true,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是true。
- x.equals(null),永远返回是false;x.equals(和x不同类型的对象)永远返回是false。
什么是hash,为什么比较equals()之前要先进行hashCode
哈希算法(又称散列算法)是将数据通过特定算法直接指定到一个地址上,可以简单理解为通过哈希算法返回的就是内存的物理地址(实际不是)。如添加不重复元素,先调用hashCode定位到对应的地址,如果该位置已经存在元素,再通过equals()比较元素是否一致。 所以,如果集合太大,一个一个比较数据会非常慢,通过比较数据之前先进行hashCode定位,可以极大减少equals()次数,有效提高效率。
为什么要重写equals
equals()和hashcode()这两个方法都是从Object类中继承过来的,Object类中的equals()是通过比较两个对象地址是否相同来返回,已经无法满足日常使用。重写equals()一般都是通过先比较hashCode是否相等,再比较值是否相等(eg:String比较同下标每一个char)。
String类并没有继承Object类,为什么可以重写Object类的方法
Object类是java所有类的父类,java中的每个类都是由它扩展而来的,不需要显式的声明(编辑器会默认加上)。
哪些类会重写equals和hashCode
集合类(List、Set、Map)、数组类、字符串类(String)、自定义类
使用了@Data,就包含了EqualsAndHashCode,重写了hashCode和equals方法。