在学习hashCode()和equals()之间的关系以前, 咱们有必要先单独了解他俩自身的特色.java
下面咱们从一个宏观的角度引入hashCode()和equals()之间的关系程序员
以上的文字是我通过思考后得出的, 它有必定依据但并不是彻底可靠, 下面咱们根据HashMap的源码(JDK1.8)和官方文档来验证这些推论是否正确.面试
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.编程
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;
复制代码
结束api