欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

遵守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类为例,编写了如下的测试用例:
 
 
@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;
}

 
  好的散列函数通常倾向于"为不相等的对象产生不相等的散列码", 否则会引起冲突,使散列表想链表退化。计算是可以把冗余的域排除在外。注意不要试图从散列码计算中排除关键域来提高性能。