为什么在没有重写 Student类 equals和 hashCode 方法时向以Student 类 为 Key 的 HashMap 添加 两个值相等的 Student 对象会添加成功,而不是 第二次 添加时 覆盖 前一次的键值对?

/**
* 为什么在没有重写 Student类 equals和 hashCode 方法时,
* 向以Student 类 为 Key 的 HashMap 添加 两个值相等的 Student 对象会添加成功,
* 而不是 第二次 添加时 覆盖 前一次的键值对?
*
* public V put(K key, V value) {
* return putVal(hash(key), key, value, false, true);
* }
*
* static final int hash(Object key) {
* int h;
* return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
* }
*
*
* 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;
* 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;
*
*
* 。。。。。。。。。。
*
* if (e != null) { // existing mapping for key
* V oldValue = e.value;
* if (!onlyIfAbsent || oldValue == null)
* e.value = value;
* afterNodeAccess(e);
* return oldValue;
* }
* }
* 1.通过底层源码,我们发现 在向 HashMap put 键值对 时,会先根据 Student对象的 hash值(由 对象的hashCode() 方法生成),
*由于 前后 put 的 两个对象的 hash 值 并不相同(因为没有重写 equals和 hashCode 方法,调用 hashCode(),
* 会调用 虚拟机的 原生方法,两个对象的原生方法返回的 hash 值并不相同)
* 这样会导致第二次 添加时(p = tab[i = (n - 1) & hash]) == null 条件为 true, 执行 tab[i] = newNode(hash, key, value, null);
* 即两个对象 将会添加在不同的 桶中
*
* 2.如果两个对象 产生的 hash 值 相同的话(需重写 Student类 equals和 hashCode 方法),则 第二次 添加时 ,(p = tab[i = (n - 1) & hash]) == null 条件为 false, 不会执行 tab[i] = newNode(hash, key, value, null);
* 而会执行
*
* if (p.hash == hash &&
* ((k = p.key) == key || (key != null && key.equals(k))))
* e = p;
*
* 最终 会 覆盖前面添加 元素的 value
*/
posted @ 2022-08-29 10:55  ___xxy  阅读(50)  评论(0)    收藏  举报