作用:hashCode()方法返回对象散列值,作用是为了快速定位对象在hash表中位置。
1.JDK的Object中,hashCode()是native方法,jvm根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称作为散列值。注意:hashCode()返回的hash值并不能表示对象的内存地址(可能计算的时候只使用了对象内存地址的一部分),最多只能说hashCode()是对象内存地址的一种表现形式,决不能说等价于内存地址。Object.equals()使用的“==”比较2对象,所以比较的是对象的内存地址是否相同。
public class Object {
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
}
2.什么时候需要重写hashCode、equals方法?
由于Object.equals()比较的是对象的内存地址是否相同,在java业务代码中基本不会直接使用内存地址比较对象是否相同,需要自定义判断2对象是否相等逻辑,所以需要重写equals()。而hashCode()方法约定了重写equals()也需要重写hashCode()。问题来了,为什么有这个约定?如果重写equals()而不重写hashCode()会发生什么情况?
首先想一下,hashCode()的作用是什么?它返回的hash值哪里会用到?
举例:一个HashSet中已经有一万条数据了,这时候新加了一条数据进来,因为HashSet集合是不允许集合元素重复的,所以首先需要进行判重。那么,如何判重?那新数据和已有的一万条数据equals()比较一万次?肯定是不可能的。所以这时候就需要hashCode()返回的对象hash值了,先通过对象的hash值得到对象在hash表中的index下标,若没有数据直接放入,若已有数据,再使用equals()方法判重,大大加快集合元素的读写。
所以,hashCode()就是用来辅助HashMap、HashSet等这些hash集合,用来快速定位元素在hash表中位置,从而加快集合的读和写。
那么不重写hashCode(),使用Object.hashCode()得到对象hash值不是也可以做到定位元素位置吗?但是它所定位到的元素位置是不正确的!
public class Admin {
int a, b, c;
public boolean equals(Object o) {
Admin admin = (Admin) o;
return a == admin.a &&
b == admin.b &&
c == admin.c;
}
}
如上所示,我们定义:Admin对象的a、b、c 3字段都相同就视为相同对象。而重写了equals()不重写hashCode()就会导致2对象就算字段a、b、c都相同,放入HashSet时也是被当成了不同对象处理!因为默认Object.hashCode()返回的是Admin对象的hash值,而不是a、b、c 3字段的hash值。不符合我们所定义的业务规则!所以,重写equals()也需要重写hashCode()!