Java Object.hashCode()方法
@(JAVA)[java]
更详细的内容可以参考《effective java》与《think in java》
Object类有一个hashCode()方法,它用于计算一个对象的hash值,同时,它也用于表示这个对象在内存中的位置。
如果一个类重写了equals()方法,则必须重写hashCode()方法。2个对象的equals()方法返回true的话,其hashCode()必须返回相同的值。否则对于HashSet, HashMap, HashTable等基于hash值的类就会出现问题。
当往HashSet(其它类似)add一个新元素时,jvm会判断这个元素是否已经存在于这个Set中,它会根据hashCode()返回的值去定位这个元素,看是否存在这个java对象。如果2个元素的equals()方法返回true,则它们应该是认为同一个元素的,但如果它们的hash值不相等,则导致jvm找不到旧的元素,从而认为新的元素不存在,导致重复插入数据。
看一下String的hashCode:
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
String是以每个字母的值来计算hash的,因此当字母相同时,String也是equals。
我们再看一下一般应该如何定义一个hashCode()方法:
public class Employee {
private String name;
private String phone;
private String address;
@Override
public boolean equals(Object obj) {
if (obj instanceof String) {
Employee other = (Employee) obj;
return (this.name.equals(other.name) && this.phone.equals(phone));
}
return false;
}
@Override
public int hashCode() {
return 7*name.hashCode() + 11*phone.hashCode();
}
public int hashCode2() {
return 7* Objects.hash(name) + 11* Objects.hash(phone);
}
public int hashCode3() {
return Objects.hash(name,phone);
}
//还有各个getter与setter。
}
我们假设当name和phone相同时,则认为这2个对象是equals的。
hashCoe()方法是传统的方法,hashCode2()和hashCode3()这2种办法都是JDK7以后支持的,可以简化代码,而且可以避免name为空之类的情形,尤其第3种。
如不需要严格控制hash值,则使用第3种。如要控制hash值,则用第2种。