hashCode()
方法的作用
在Java中,hashCode
方法的主要作用是为了配合基于散列的集合一起正常运行,这样的散列集合包括HashSet
、HashMap
以及HashTable
。
用HashMap
举例说明下,为了判断HashMap
中存在不存在key,HashMap
不用遍历里面的所有元素进行判断再取值,为什么呢?HashMap
类中维护了一个数组(俗称桶或箱子),桶的类型是链表或者红黑树,每次进行put
运算时,都会对key
的hashCode
值进行hash
运算,得到的hash
值与数组元素的个数进行与运算,目的是拿到该key对应的桶的位置,即数组索引下标,再遍历桶(链表或红黑树)判断key是够存在,这样只需遍历对应桶的元素即可。同时,为了让HashMap
中的元素尽量发散,即尽可能每个桶的元素都平均,不会出现其中一个桶元素很多,其他桶元素很少的情况,于是使用hashCode
方法进行hash运算,让各个元素都发散到各个桶中,减少遍历桶元素的时间,大大提高了HashMap
的性能。
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
// 计算hash值,并找到key对应的table桶位置
if ((p = tab[i = (n - 1) & hash]) == null)
// 该桶元素为空,直接放元素进去该桶
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
// 总是比较第一个元素
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
// 桶是红黑树
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
// 遍历桶里面的元素并比较是否eqlues等于key
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
......
}
......
}
2. equals()
和hashCode()
方法
重写equals
方法的同时,必须重写hashCode
方法,因为重写了equals
方法后,如果有散列集合操作的话,如HashMap
的put
操作,需要使用hashCode
方法进行hash
运算,如果equals
相等的两个类,但是无法保证hashCode
方法返回的值一样,如果这两个类分别进行put
操作的话,可能会保存到不同的数组下标中而不是同一个。