Set,Map等类会首先调用对象的hashCode(),根据返回的hash值比较对象是否相同(一般情况下可提高性能)。如果两个对象返回的hash值相同,则再调用对象的equals()进行比较。
以下类覆盖了equals(),使用phoneNumber比较对象是否相同:
package com.bingo.practice.effective.three.nine;
public class PhoneNumber {
private int phoneNumber;
public PhoneNumber(int phoneNumber){
this.phoneNumber=phoneNumber;
}
public int getPhoneNumber(){
return this.phoneNumber;
}
@Override
public boolean equals(Object obj) {
if(obj==this)return true;
if(!(obj instanceof PhoneNumber))return false;
PhoneNumber target=(PhoneNumber)obj;
return this.phoneNumber==target.getPhoneNumber();
}
}
以下测试将失败,尽管phoneNumber1和phoneNumber2是相同的(phoneNumber属性值都是123),但是由于未覆盖hashCode(),两者返回的hash值是不同的。当使用phoneNumber2作为key从hashmap里获取值时,hashmap判断自身不包含phoneNumber2返回的hash值,因此直接返回null。
@Test
public void testHashCode(){
PhoneNumber phoneNumber1=new PhoneNumber(123);
PhoneNumber phoneNumber2=new PhoneNumber(123);
Map<PhoneNumber, String> container=new HashMap<PhoneNumber, String>();
container.put(phoneNumber1, "bingo");
Assert.assertEquals(container.get(phoneNumber2), "bingo");
}
PhoneNumber覆盖hashCode()后,以上测试将通过,代码如下:
@Override
public int hashCode() {
return phoneNumber;
}
覆盖hashCode的基本原则:
1.如果两个对象使用equals()比较是相同的,那么hashCode()必须返回相同的值
2.如果两个对象是不同的,hashCode()可以返回相同的值。但是建议返回不同的值以提高性能
需要注意的地方:
1.Object的hashCode()一般返回对象的内存地址作为hash值,但是也可能对两个不同的对象返回相同的hash值(与JVM的实现有关)
2.推荐使用Apache Commons的HashCodeBuilder覆盖hashCode()