什么是hashCode()

HashCode()是java.lang.Object中定义的一种方法,用于返回一个散列值。在Java语言中,所有的类都要提供一个HashCode()方法。散列值被用来将对象分类,以实现快速存储和检索。默认情况下,每个类继承实现java.lang.Object提供的HashCode(),但是这对于特殊的用户可能不会是高效或者精确的,因此,很多类覆盖了这个方法。

The Contract

Java语言中提供了两个有关联的方法hashCode()和equals()。如果两个对象使用equals()返回true,那么使用hashCode()也会返回相同的散列值。但是,当两个对象使用equals()返回false,使用hashCode()不一定会返回不同的散列值。需要记住的是,如果两个对象使用equals()返回true,那么使用hashCode()方法会返回相同的散列值。当你覆盖equals()方法时,要同时覆盖hashCode()方法。Always override hashCode and equals together!

一个相关的例子(源代码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import java.util.HashMap;
public class Apple {
private String color;
public Apple(String color) {
this.color = color;
}
public boolean equals(Object obj) {
if (!(obj instanceof Apple))
return false;
if (obj == this)
return true;
return this.color.equals(((Apple) obj).color);
}
public static void main(String[] args) {
Apple a1 = new Apple("green");
Apple a2 = new Apple("red");
//HashMap中存储苹果类型及其数量
HashMap<Apple, Integer> m = new HashMap<Apple, Integer>();
m.put(a1, 10);
m.put(a2, 20);
System.out.println(m.get(new Apple("green")));
}
}

此时运行程序的结果是:

1
null

同时覆盖hashCode(),即添加代码:

1
2
3
4
5
6
//这里仅以此为例
public int hashCode(){
return this.color.length();
}

此时运行程序的结果是:

1
10

怎么覆盖hashCode()

如果要实现存储对象的集合的存储和检索效率最大化,需要提供一个完美的散列函数。实现散列函数的基本目标是,提供散列值的统一分配。统一分配意味着,N个可能的返回结果具有相同的返回概率1/N。很难在实际中提供一个完美的散列函数。

实现散列函数的方法
  • Apache Commons包有一个HashCodeBuilder可以用来提供hashCode()的实现:
1
2
3
4
5
6
7
8
9
10
11
Class Employee {
String name;
int empId;
public int hashCode() {
//5和7是随机选择的两个数
return new HashCodeBuilder(5, 7). append(name).append(empId).toHashCode();
}
}
  • 使用IDE(集成开发环境)提供的典型实现方法:

例如,在Eclipse中,right click on class >> source > Generate hashCode() and equals() …

  • Apache Commons包中的EqualsBuilder可以用来提供equals()的实现。

参考资料:

Java Hashcode and equals – Most Important Things to Consider