遵守equals和hashCode方法的通用约定 (2)
程序员文章站
2022-03-31 09:36:56
...
如前文所述,在覆盖了equals方法的类中,也必须覆盖hashCode方法。否则违反了Object.hashCode的通用约定会导致该类无法和基于散列的集合(HashMap,HashSet和HashTable)一起正常使用。
如下约定内容摘自Object规范:
1. 在应用程序中,只要对象的euqals方法的比较操作所用的信息没有修改,那么对于同一个对象的调用多次hashCode,必须始终如一返回同一个哈希值。
2. 如果两个对象通过equals比较相等,那么它们的哈希值相同。
3. 如果两个对象通过euqals比较不等,他们的哈希值可能相同,取决于hashCode的实现,由此散列表的性能也会有区别。
以前面的PhoneNumber类为例,编写了如下的测试用例:
发现测试失败了,但是两个对象通过equals比较是相等的。由于并没有覆盖hashCode方法导致两个相等的对象不能获得相同的散列码。根据约定重写hashCode:
好的散列函数通常倾向于"为不相等的对象产生不相等的散列码", 否则会引起冲突,使散列表想链表退化。计算是可以把冗余的域排除在外。注意不要试图从散列码计算中排除关键域来提高性能。
如下约定内容摘自Object规范:
1. 在应用程序中,只要对象的euqals方法的比较操作所用的信息没有修改,那么对于同一个对象的调用多次hashCode,必须始终如一返回同一个哈希值。
2. 如果两个对象通过equals比较相等,那么它们的哈希值相同。
3. 如果两个对象通过euqals比较不等,他们的哈希值可能相同,取决于hashCode的实现,由此散列表的性能也会有区别。
以前面的PhoneNumber类为例,编写了如下的测试用例:
@Test public void testHashCode(){ PhoneNumber pn1 = new PhoneNumber(86, "12345"); PhoneNumber pn2 = new PhoneNumber(86, "12345"); Map<PhoneNumber,String> map = new HashMap<PhoneNumber,String>(); map.put(pn1, "12345"); assertNotNull(map.get(pn2)); }
发现测试失败了,但是两个对象通过equals比较是相等的。由于并没有覆盖hashCode方法导致两个相等的对象不能获得相同的散列码。根据约定重写hashCode:
@Override public int hashCode(){ int result = 17; result = 31 * result + countryCode; if(nationalNumber != null) result = 31 * result + nationalNumber.hashCode(); return result; }
好的散列函数通常倾向于"为不相等的对象产生不相等的散列码", 否则会引起冲突,使散列表想链表退化。计算是可以把冗余的域排除在外。注意不要试图从散列码计算中排除关键域来提高性能。
推荐阅读
-
一文搞懂hashCode()和equals()方法的原理
-
java类中的equals、hashCode和toString方法
-
java实体类中equals和hashCode方法的重写
-
荐 equals和hashCode的约定(重写equals必须重写hashCode)
-
java中“==”和equals()的区别、hashCode()、为什么重写equals()方法必须重写hashCode()
-
遵守equals和hashCode方法的通用约定 (1)
-
关于Hibernate ORM映射实体通用hashCode与equals方法的实现
-
关于Hibernate ORM映射实体通用hashCode与equals方法的实现
-
一文搞懂hashCode()和equals()方法的原理
-
Object类和类中常用的方法:hashCode(),getClass(),toString(),equals(Object obj)(默认),clone();