HashCode介绍
hashCode简介
public int hashCode()
:hashCode是根类Obeject中的方法。默认情况下,Object类中的hashCode() 返回对象的32位JVM内存地址。也就是说如果对象不重写该方法,则会返回相应对象的32位JVM内存地址。
Object类中hashCode()源码
public native int hashCode();
hashCode作用
HashCode的存在主要是为了查找的快捷性,HashCode是用来在散列存储结构中确定对象的存储地址的(即对象在hash表中的位置);
equals方法和hashCode的关系
- 如果两个对象equals相等,那么这两个对象的HashCode一定也相同;
- 如果两个对象的HashCode相同,不代表两个对象就相同,只能说明这两个对象在散列存储结构中,存放于同一个位置;
- 重写了equals方法的对象必须同时重写hashCode()方法;
案例:
若只重写equals方法则会出现以下情况:
package com.test;
import java.util.HashMap;
public class HashCodeTest {
int clazz = 1;
// 重写equals方法
@Override
public boolean equals(Object obj) {
return this.clazz == ((HashCodeTest) obj).clazz;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
HashCodeTest demo1 = new HashCodeTest();
HashCodeTest demo2 = new HashCodeTest();
System.out.println(demo1.equals(demo2));// true
System.out.println(demo1.hashCode()); // 366712642
System.out.println(demo2.hashCode()); // 1829164700
System.out.println("------------------");
HashMap map = new HashMap();
/**
* 如果map中已经存在该key,那么put该key-value时返回的是旧的value;
* put()方法实现:首先hash(key)得到key的hashcode(),hashMap根据获得的hashCode找到要插入的位置所在的链
*/
map.put(demo1 , demo1);
map.put(demo2 , demo2);
// 理论上讲第二次put会被第一次put覆盖,只会有一个
System.out.println(map);
/*{com.test.HashCodeTest@15db9742=com.test.HashCodeTest@15db9742,
com.test.HashCodeTest@6d06d69c=com.test.HashCodeTest@6d06d69c}/*
}
}
重写hashCode时注意事项
重写hashCode方法时除了上述一致性约定,还有以下几点需要注意:
(1)返回的hash值是int型的,防止溢出;
(2)不同的对象返回的hash值应该尽量不同(为了hashMap等集合的效率问题);
(3)《Java编程思想》中提到一种情况:
“设计hashCode()时最重要的因素就是:无论何时,对同一个对象调用hashCode()都应该产生同样的值。如果在讲一个对象用put()添加进HashMap时产生一个hashCdoe值,而用get()取出时却产生了另一个hashCode值,那么就无法获取该对象了。所以如果你的hashCode方法依赖于对象中易变的数据,用户就要当心了,因为此数据发生变化时,hashCode()方法就会生成一个不同的散列码”。