散列码( hash code ) 是由对象导出的一个整型值。散列码是没有规律的。如果 x 和 y 是两个不同的对象, x.hashCode( ) 与 y.hashCode( ) 基本上不会相同。 在表 5- 1 中列出 T 几个通过调用 String 类的 hashCode 方法得到的散列码。
由于 hashCode方法定义在 Object 类中, 因此每个对象都有一个默认的散列码,其值为对象的存储地址。
Object 中的 hashCode 方法:
public native int hashCode(); // 原生的方法,非Java实现
String 类使用下列算法计算散列码:
// String 类中的 hashCode [JDK 1.8 ]
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;
}
如果重新定义 equals方法,就必须重新定义 hashCode 方法, 以便用户可以将对象插人到散列表中。
hashCode 方法应该返回一个整型数值(也可以是负数,) 并合理地组合实例域的散列码,以便能够让各个不同的对象产生的散列码更加均匀。
例如, 下面是 Employee 类的 hashCode 方法
public class Employee{
public int hashCode(){
return 7 * name.hashCode()
+ 11 * new Double(salary).hashCode()
+ 13 * hireDay.hashCode();
}
...
}
不过,还可以做得更好。首先, 最好使用 null 安全的方法 Objects.hashCode。 如果其参数为 null,这个方法会返回 0, 否则返回对参数调用 hashCode 的结果。
public int hashCode(){
return 7 * Objects.hashCode(name)
+ 11 * Double.hashCode(salary)
+ 13 * Objects.hashCode(hireDay)
}
还有更好的做法,需要组合多个散列值时,可以调用 ObjeCtS.hash 并提供多个参数。这个方法会对各个参数调用Objects.hashCode, 并组合这些散列值。这样 Employee.hashCode 方法可以简单地写为:
public int hashCode(){
return Objects.hash(name, salary, hireDay);
}
Equals 与 hashCode 的定义必须一致:如果 x.equals(y) 返回 true, 那么 x.hashCode( ) 就必须与 y.hashCode( ) 具有相同的值。例如, 如果用定义的 Employee.equals 比较雇员的 ID,那么 hashCode 方法就需要散列 ID,而不是雇员的姓名或存储地址。
提示:如果存在数组类型的域, 那么可以使用静态的 Arrays.hashCode 方法计算一个散列码,这个散列码由数组元素的散列码组成。
java.util.Object 1.0
•int hashCode( )
返回对象的散列码。散列码可以是任意的整数, 包括正数或负数。两个相等的对象要求返回相等的散列码。
java.util.Objects 7
•static int hash(Object . .. objects)
返回一个散列码,由提供的所有对象的散列码组合而得到。
•static int hashCode(Object a )
如果 a 为 null 返回 0, 否则返回 a.hashCode() 0
java.lang.(lnteger|Long|Short|Byte|Double|Float|Character|Boolean) 1.0
•static int hashCode((int11ong|short|byte|double|f1oat|char|boolean) value) 8
返回给定值的散列码。
java.utii.Arrays 1.2
•static int hashCode(type[] a ) 5.0
计算数组 a 的散列码。组成这个数组的元素类型可以是 object,int,long, short, char,byte, boolean, float 或 double。