目录
在学习hashCode()和equals()之间的关系之前, 我们有必要先单独了解他俩自身的特点.
?
?
下面我们从一个宏观的角度引入hashCode()和equals()之间的关系
?
?
?
?
以上的文字是我经过思考后得出的, 它有一定依据但并非完全可靠, 下面我们根据HashMap的源码(JDK1.8)和官方文档来验证这些推论是否正确.
通过阅读JDK8的官方文档, 我们发现equals()方法介绍的最后有这么一段话:
Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
在HashMap中用得最多无疑是put()方法了, 以下是put()的源码:
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
//在我们创建HashMap对象的时候, 内存中并没有为HashMap分配表的空间, 直到往HashMap中put添加元素的时候才调用resize()方法初始化表
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;//同时确定了表的长度
//((n - 1) & hash)确定了要put的元素的位置, 如果要插入的地方是空的, 就可以直接插入.
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))))
//关键!!!当判断新加入的元素是否与已有的元素相同, 首先判断的是hash值, 后面再调用equals()方法. 如果hash值不同是直接跳过的
e = p;
else if (p instanceof TreeNode)//如果冲突解决方案已经变成红黑树的话, 按红黑树的策略添加结点.
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {//解决冲突的方式仍是链表
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;
}//在遍历的过程中仍会不停地判定当前key是否与传入的key相同, 判断的第一条件仍然是hash值.
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;//修改map的次数增加
if (++size > threshold)//如果hashMap的容量到达了一定值就要进行扩容
resize();
afterNodeInsertion(evict);
return null;
}
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
结束
从语言设计的角度探究Java中hashCode()和equals()的关系
原文:https://www.cnblogs.com/tanshaoshenghao/p/10915055.html