作用:
返回该对象的hashcode值,作用为了提高查询效率,为了配合散列的集合一起使用,类似于这样的散列集合有,hashset,hashmap,hashtable
哈希码的通用约定如下:
在java程序执行过程中,在一个对象没有被改变的前提下,无论这个对象被调用多少次,hashCode方法都会返回相同的整数值。对象的哈希码没有必要在不同的程序中保持相同的值。
如果2个对象使用equals方法进行比较并且相同的话,那么这2个对象的hashCode方法的值也必须相等。
如果根据equals方法,得到两个对象不相等,那么这2个对象的hashCode值不需要必须不相同。但是,不相等的对象的hashCode值不同的话可以提高哈希表的性能。
通常情况下,不同的对象产生的哈希码是不同的。默认情况下,对象的哈希码是通过将该对象的内部地址转换成一个整数来实现的。
源码:
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
hashcode在hashmap中的应用
当你往集合里插入一个对象,散列集合是不允许重复的元素存在,先调用找个对象的hashcode方法,得到hashcode值,以hashmap为例,具体实现中会以有一个table来存储已经存进去对象的hashcode值,如果table里面没有该hashcode值,就直接存进去了,如果存在,就调用eq方法,相同就不存了,覆盖掉value值,hashcode方法的存在就是为了减少eq方法的调用次数,提高程序效率
//只重写了hashcode方法
Person a = new Person("a");
Person b = new Person("b");
HashMap<Object, Object> map = new HashMap<>();
map.put(a,"f1");
map.put(b,"f2");
System.out.println("map = " + map);
//结果如下
//map = {Person{name='b'}=f2, Person{name='a'}=f1}
上面代码中,hashmap中存入了a,b两个对象,但是这2个元素是在哈希表中的同一个数组项中的位置,也就是在同一串链表中。为什么,a和b的hashcode值相同,但是确存入到了map中,因为hashmap判断重复数据的条件是 两个对象的hash码相同,且eq方法比较得到的结果为true
这个时候如果再重写eq方法,得到的就只有一个对象了。
相同对象的hashcode值不一定相同,相同hashcode值的对象不一定是相同对象
两个对象的hashcode值不同,那么一定是两个不同的对象
两个对象的eq方法不同,hashcode值一定不同
两个对象的eq方法相同,hashcode值也一定相同,否则就违背了违反了通用约定的第二点
重写eq方法的同时必须重写hashcode方法
创建了一个对象,new person( jack ),把他存入hashmap里,值为18,使用hashmap.get(new person( jack )) ,正常情况下,如果两个person对象,值都一样,则认为是同一个, 在这里的意愿是想输出存入的1,事实上得到的结果为null
要知道默认情况下,hashcode方法是将对象的存储地址进行映射,
new person( jack ) 和 hashmap.get(new person( jack )) 生成的是2个对象,他们的存储地址不同,先进行了hashcode运算,也是有几率会两个对象的hashcode是一样的, 这样的几率非常小,
设计hashcode的重要因素:: 无论何时,对同一个对象调用hashcode都应该产生相同的,如果一个对象用put添加进hashmap时产生一个hashcode值,get取出的时候产生了另一个hashcode值,就无法获取该对象,