JCF之equals()与hashCode()关系详解 (一)

2014-11-24 07:51:04 · 作者: · 浏览: 2

上一篇http://www.2cto.com/kf/201204/128923.html分析了equals()与==的区别,这一篇,我们将一窥equals()与hashcode()的关系。

API对于quals()的定义在上篇中已经解释过,这里再现一下:

[java] /*
equals 比较非空对象引用
自反性,x.equals(x)返回true
对称性:x.equals(y)与y.equals(x)结果相同
传递性:如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)返回true
一致性:多次执行x.equals(y)的结果相同
对于任何非空引用x,x.equals(null)返回false;
*/
public boolean equals(Object obj) {
return (this == obj);
}
/*
equals 比较非空对象引用
自反性,x.equals(x)返回true
对称性:x.equals(y)与y.equals(x)结果相同
传递性:如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)返回true
一致性:多次执行x.equals(y)的结果相同
对于任何非空引用x,x.equals(null)返回false;
*/
public boolean equals(Object obj) {
return (this == obj);
}

OK!现在,接下来让我们来看一下JDk 1.5 documentation中关于hashCode()的描述:

Returns a hash code value for the object. This method is supported for the benefit of hashtables such as those provided by java.util.Hashtable.

The general contract of hashCode is:

· Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the

same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution

of an application to another execution of the same application.

· If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same

integer result.

· It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the

two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects

may improve the performance of hashtables.

As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically

implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)


大意如下:

返回对象的hashCode值.为hash类容器的使用提供支持。

hashCode基本规范:


在一个Java应用程序执行期间,如果一个对象中与equals()相关的信息没有被修改,那么,每次调用hashCode()都会返回同一个int值(hashCode)
假设有两个对象x,y;如果x.equals(y)==true,则x.hashCode()与y.hashCode()得到的值必须相等
假设有两个对象x,y;如果x.equals(y)==false,则,则x.hashCode()与y.hashCode()得到的值可能相等,也可能不相等

这一基本规范也可以概括为一句话:

如果两个对象相等(x.equals()==true),则它们的hashCode相等;

如果两个对象不等(x.equals()==false),则它们的hashCode可能相等,也可能不相等。


这一规范导致了一个重要的衍生规范:

如果我们设计的Class重写了equals()方法,也需要重写hashCode()方法。

这一衍生规范还是很好理解的,如果只重写equals()而不重写hashCode(),那么当equals()为true时,hashCode不能保证相等,违反了hashCode的基本规范。

比如String中就重写了hashCode():

[java] public int hashCode() {
int h = hash;
if (h == 0) {
int off = offset;
char val[] = value;
int len = count;
for (int i = 0; i < len; i++) {
h = 31*h + val[off++];
}
hash = h;
}
return h;
}
public int hashCode() {
int h = hash;
if (h == 0) {
int off = offset;
char val[] = value;
int len = count;
for (int i = 0; i < len; i++) {
h = 31*h + val[off++];
}
hash = h;
}
return h;
}改写后的hashCode()的返回值只与String的具体字符有关,即与其内容有关。


那么,为什么要对hashCode作出这样的规范呢?

前面的章节中已经探讨过Hashtable、HashMap的实现,应该感受到了hashCode的重要性。