再学习HashMap

Hash Map:

  1. null 键哈希值为 0
  2. 扰动计算,(h = key.hashCode()) ^ (h >>> 16)
  3. 初始化容量16( 2 的倍数,寻找2的倍数用的右移或运算,然后+1),负载因子默认0.75
  4. 原 jdk1.7 中会需要重新计算哈希值,但是 到 jdk1.8 中已经进行优化,不在需要重新计算

hashmap存放元素流程:

  1. 计算hash值
  2. 判断tab是否为空或长度为0,是则初始化
  3. 计算下标,tab[i = (n - 1) & hash]),并判断下标位置是否为空
    1. 是则直接新建node
    2. 不是则需要覆盖
      1. 如果是树节点,则直接插入树中
      2. 如果是链表,则遍历链表并插入链表,然后判断链表插入前的长度是否>=7(第9个元素时扩容 >8);
        1. 是则转化为红黑树,转化为红黑树之前,会判断当前数组的长度是否<64,小于64则扩容而不是转化为红黑树
    3. 完成插入之后,会判断当前是否超过阈值,超过则扩容
for (int binCount = 0; ; ++binCount) {  // 从0开始
            if ((e = p.next) == null) {
                p.next = newNode(hash, key, value, null); // 插入了元素,但是binCount是没有+1的
                if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st,此时binCount == 7,已经是第8个元素了,加上刚插入的,所以是第9个元素时变成树 >8
                    treeifyBin(tab, hash);
                break;
            }
            if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) {
                break;
            }
            p = e;
        }

posted on 2022-04-11 23:00  灰马非马  阅读(22)  评论(0编辑  收藏  举报

导航