散列码(hash code)是由对象导出的一个整型值。散列码是没有规律的,并且如果x和y是两个不同的对象,那么x的hash code与y的hash code基本上不会相同。对象间进行比较时,默认比较的是两个对象的hash code的值是否相同。
在Object类中定义了一个hashcode()的方法,因此每一个对象都有一个默认的hash code,其值为该对象存储的地址。
我们可以自己定义一个类来验证一下:
public class HashCodeDemo {
public static void main(String[] args) {
Node n1 = new Node("a",10);
Node n2 = new Node("a",10);
System.out.println("n1 equals n2?" + n1.equals(n2));
System.out.println("n1 hashcode: " + n1.hashCode());
System.out.println("n2 hashcode: " + n2.hashCode());
}
}
class Node{
String name;
int age;
Node(String _name, int _age){
this.name = _name;
this.age = _age;
}
}
/*
输出:
n1 equals n2?false
n1 hashcode: 366712642
n2 hashcode: 1829164700
*/
可以发现,两个对象即使类型一样,内部属性也一样,其hashcode值也是不同的,这显然不符合我们使用equal()方法的需要。事实上,许多常用的对象内部都重写了hashcode方法。例如,Integer重写了hashcode,返回的是其内部的值;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;
}
我们也可以通过一个例子来验证:
public class HashCodeDemo {
public static void main(String[] args) {
Integer i1 = Integer.valueOf(3);
Integer i2 = Integer.valueOf(3);
System.out.println("i1 equals i2?" + i1.equals(i2));
System.out.println("i1 hashcode: " + i1.hashCode());
System.out.println("i2 hashcode: " + i2.hashCode());
String s1 = "STR";
String s2 = "STR";
System.out.println("s1 equals s2?" + s1.equals(s2));
System.out.println("s1 hashcode: " + s1.hashCode());
System.out.println("s2 hashcode: " + s2.hashCode());
}
}
/*
输出:
i1 equals i2?true
i1 hashcode: 3
i2 hashcode: 3
s1 equals s2?true
s1 hashcode: 82449
s2 hashcode: 82449
*/
我们在定义类的时候也可以自己来实现其hashcode方法,且eclipse能够根据类的属性,自动生成其的hashcode方法:
public class HashCodeDemo {
public static void main(String[] args) {
NodeWithHash nw1 = new NodeWithHash("a",10);
NodeWithHash nw2 = new NodeWithHash("a",10);
System.out.println("nw1 equals nw2?" + nw1.equals(nw2));
System.out.println("nw1 hashcode: " + nw1.hashCode());
System.out.println("nw2 hashcode: " + nw2.hashCode());
}
}
class NodeWithHash{
String name;
int age;
NodeWithHash(String _name, int _age){
this.name = _name;
this.age = _age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
NodeWithHash other = (NodeWithHash) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
/*
输出:
nw1 equals nw2?true
nw1 hashcode: 1368
nw2 hashcode: 1368
*/