散列碼(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
*/