`

[转]关于hashcode与equal函数

阅读更多

 

hashcode:独一无二地代表了一个对象,并且通过hashcode可以找到这个对象。(比价不准确的说法)

在java.lang.Object的规范中,对hasCode有如下的约定:

 1 在一个应用程序执行期间,如果一个对象的equals方法做比较所用到的信息没有被修改的话,那么对该对象调用多次hashCode方法,它必须返回相同的整数。在同一程序的多次执行过程中,这个整数方法可以不同。

2 如果两个对象根据equals方法是相等的,那么调用这两个对象的hashCode方法必须产生同样的整数结果。

3 如果两个对象根据equals方法是不相等的,那么调用这两个对象的hashCode方法,不要求产生不同的整数结果。

只是为了维护 hashCode 方法的常规协定,才要求用equals比较的两个对象的hashCode相同.

 

equals()和hashCode()都来自java.lang.Object.你当然可以重写.

 

比如a.equals(b).仅当a的内存地址相等时,才返回true.当然如String等类已经对这个方法进行了重写,比较的就不再是内存地址了.

 

hashCode()的值也是与内存地址相关的.所以仅当内存地址相等时,hashCode才相等.同样很多类也重写了这个方法,还是以String为例:

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;

}

就不在与内存地址相关了.这样做是为了保证用equals比较返回为true的两个对象,他们的hashCode是相同的.

 

所以一般重写equals的时候都会重写hashCode().

 

当然,这个相当于一个约定,一个协议.你不这么做并不会错.

 

hash code、equals和“==”三者的关系

1.如果是基本变量,没有hashcode和equals方法,基本变量的比较方式就只有==;

 

2.如果是变量,由于在java中所有变量定义都是一个指向实际存储的一个句柄(你可以理解为c++中的指针),在这里==是比较句柄的地址(你可以理解为指针的存储地址),而不是句柄指向的实际内存中的内容,如果要比较实际内存中的内容,那就要用equals方法,但是!!!

 

如果是你自己定义的一个类,比较自定义类用equals和==是一样的,都是比较句柄地址,因为自定义的类是继承于object,而object中的equals就是用==来实现的,你可以看源码。

 

那为什么我们用的String等等类型equals是比较实际内容呢,是因为String等常用类已经重写了object中的equals方法,让equals来比较实际内容,你也可以看源码。

 

3. hashcode

在一般的应用中你不需要了解hashcode的用法,但当你用到hashmap,hashset等集合类时要注意下hashcode。

 

你想通过一个object的key来拿hashmap的value,hashmap的工作方法是,通过你传入的object的hashcode在内存中找地址,当找到这个地址后再通过equals方法来比较这个地址中的内容是否和你原来放进去的一样,一样就取出value。

 

所以这里要匹配2部分,hashcode和equals

但假如说你new一个object作为key去拿value是永远得不到结果的,因为每次new一个object,这个object的hashcode是永远不同的,所以我们要重写hashcode,你可以令你的hashcode是object中的一个恒量,这样永远可以通过你的object的hashcode来找到key的地址,然后你要重写你的equals方法,使内存中的内容也相等。。。

== 是比较地址是否相等,JAVA中声明变量都是引用嘛,不同的引用,可能指向同一个地址。

 

equals 是比较值是否相等。

(原文:http://blog.sina.com.cn/s/blog_52fea7b60100brce.html)

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics