HashMap源码精讲

1.底层存储结构
底层存储结构为数组+链表+红黑树,当单个链表长度≥8且总存量达到64时,链表会进化为红黑树,更利于插入和查找

2.hashcode

  • 相等(相同)的对象必须具有相等的哈希码(或者散列码)。
  • 如果两个对象的hashCode相同,它们并不一定相同。
    即两个对象equal()后是一样的,则hashcode()一定一样,但反之不同。
    3.hashmap.put
    在这里插入图片描述
  • 扰动函数(hash方法):将hashcode与hashtable表长进行“与”&运算,以此降低冲突的概率
static final int hash(Object key) {
    
    
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
    

3.resize()扩容
为了解决哈希冲突导致的链化,从而影响查询效率,所以需要扩容

final Node<K,V>[] resize() {
    
    
        Node<K,V>[] oldTab = table;
        //oldTap:引用扩容器前的哈希表
        //oldCap:扩容前table数组的长度
        int oldCap = (oldTab == null) ? 0 : oldTab.length;
        //oldThr:触发本次扩容的阈值
        int oldThr = threshold;
        //newCap:扩容后table数组的大小
        //newThr:扩容后再次触发扩容的阈值
        int newCap, newThr = 0;
        //条件如果成立,说明HashMap中散列表已经初始化过了,是一次正常的扩容
        if (oldCap > 0) {
    
    
        //数组已经达到最大阈值,则更改阈值为int最大值(几乎不可能再达到的值)
            if (oldCap >= MAXIMUM_CAPACITY) {
    
    
                threshold = Integer.MAX_VALUE;
                return oldTab;
            }
            //左移一位等于翻一倍,即新数组为原来数组的二倍,在小于最大容量且大于初始容量的情况下,将阈值翻倍
            else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
                     oldCap >= DEFAULT_INITIAL_CAPACITY)//默认为16
                newThr = oldThr << 1; // double threshold
        }
        //oldThr有值有以下几种情况
        //1.new HashMap(initCap,loadFactor)
        //2.new HashMap(initCap)
        //3.new HashMap(map)
        else if (oldThr > 0) // initial capacity was placed in threshold
            newCap = oldThr;
      //oldCap和oldThr都为0,给上默认值
        else {
    
                   // zero initial threshold signifies using defaults
            newCap = DEFAULT_INITIAL_CAPACITY;
            newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
        }
        //newThr为0时,通过newCap * loadFacto计算出来值赋给它
        if (newThr == 0) {
    
    
            float ft = (float)newCap * loadFactor;
            newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
                      (int)ft : Integer.MAX_VALUE);
        }
        threshold = newThr;
        @SuppressWarnings({
    
    "rawtypes","unchecked"})
        //创建出一个更大更强的数组
        Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
        table = newTab;
        //扩容前,table不为空
        if (oldTab != null) {
    
    
            for (int j = 0; j < oldCap; ++j) {
    
    
            //e为当前node节点
                Node<K,V> e;
                //j=0,所以是将头节点赋值给e,若头节点不为空,条件成立
                if ((e = oldTab[j]) != null) {
    
    
                // 将 oldTab[j]置为空,方便JVM进行GC
                    oldTab[j] = null;
                    //1.若只有单个节点,则直接将老表内的值(e)移入新表,地址为[e.hash & (newCap - 1)] 
                    if (e.next == null)
                        newTab[e.hash & (newCap - 1)] = e;
                        //2.当前节点已经树化
                    else if (e instanceof TreeNode)
                        ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
                        //3.桶位已经形成链表
                    else {
    
     // preserve order
                        Node<K,V> loHead = null, loTail = null;
                        Node<K,V> hiHead = null, hiTail = null;
                        Node<K,V> next;
                        do {
    
    
                            next = e.next;
                            if ((e.hash & oldCap) == 0) {
    
    
                                if (loTail == null)
                                    loHead = e;
                                else
                                    loTail.next = e;
                                loTail = e;
                            }
                            else {
    
    
                                if (hiTail == null)
                                    hiHead = e;
                                else
                                    hiTail.next = e;
                                hiTail = e;
                            }
                        } while ((e = next) != null);
                        if (loTail != null) {
    
    
                            loTail.next = null;
                            newTab[j] = loHead;
                        }
                        if (hiTail != null) {
    
    
                            hiTail.next = null;
                            newTab[j + oldCap] = hiHead;
                        }
                    }
                }
            }
        }
        return newTab;
    }

以上内容全为笔者手打,欢迎大家一起交流学习!!

猜你喜欢

转载自blog.csdn.net/weixin_40485391/article/details/107296338