`
zhuyuyuseu
  • 浏览: 8751 次
  • 性别: Icon_minigender_1
  • 来自: 南通
社区版块
存档分类
最新评论

遵守equals和hashCode方法的通用约定 (2)

    博客分类:
  • Java
阅读更多
  如前文所述,在覆盖了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;
}

 
  好的散列函数通常倾向于"为不相等的对象产生不相等的散列码", 否则会引起冲突,使散列表想链表退化。计算是可以把冗余的域排除在外。注意不要试图从散列码计算中排除关键域来提高性能。
分享到:
评论
2 楼 Vicky.Hu 2014-02-25  
看完顿时醍醐灌顶啊!  
1 楼 seaboycs 2014-02-25  
此乃神作,作者神人也!

相关推荐

Global site tag (gtag.js) - Google Analytics