HashMap源码追踪(1.8版本)——put方法流程追踪、扩容resize()、树化treeifyBin()

put方法流程追踪

1、put

public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

在这里插入图片描述
在这里插入图片描述
进入resize方法

2、resize

图1
在这里插入图片描述
新的阈值
在这里插入图片描述
创建数组,赋值给table属性
图2
在这里插入图片描述
回到put方法,根据计算获取数组下标位置,并从table数组中取出Node节点
在这里插入图片描述
如果不存在则创建新的节点对象
在这里插入图片描述
图3
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第一次resize是进行了table的初始化赋值,此时进入resize真正进行扩容(接图2)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
低位的则放入新数组的下标位置等于老的下标位置,高位则放入下标位置+老的容量
在这里插入图片描述

3、treeifyBin(接图3)

当Node链表长度达到了树化阈值,时,触发treeifyBin方法
在这里插入图片描述
在这里插入图片描述
截至当前,主要将链表中每个节点拿出来进行转换成TreeNode类型
重点关注treeify方法

       final void treeify(Node<K,V>[] tab) {
            TreeNode<K,V> root = null;
            //this为调用者,此时为hd即TreeNode头节点
            for (TreeNode<K,V> x = this, next; x != null; x = next) {
                //获取头节点的下一个节点
                next = (TreeNode<K,V>)x.next;
                //赋值头节点的左右child为null
                x.left = x.right = null;
                if (root == null) {
                    x.parent = null;
                    x.red = false;
                    //将头节点赋值给root
                    root = x;
                }
                else {
                    //此时x为头节点的next节点,获取其key值
                    K k = x.key;
                    //获取节点的hash值
                    int h = x.hash;
                    Class<?> kc = null;
                    for (TreeNode<K,V> p = root;;) {
                        //此时p为树的根节点,
                        int dir, ph;
                        K pk = p.key;
                        if ((ph = p.hash) > h)
                            dir = -1;
                        else if (ph < h)
                            dir = 1;
                        else if ((kc == null &&
                                  (kc = comparableClassFor(k)) == null) ||
                                 (dir = compareComparables(kc, k, pk)) == 0)
                            dir = tieBreakOrder(k, pk);

                        TreeNode<K,V> xp = p;
                        //hash比较大小,小的放左边,大的放右边
                        //获取头节点的左节点/右节点,并重新赋值给p
                        //(此时为根节点的下一级节点)
                        //如果不为null则继续循环
                        if ((p = (dir <= 0) ? p.left : p.right) == null) {
                          //将当前xp赋值给x的父级节点属性(x为要处理的TreeNode)
                            x.parent = xp;
                            if (dir <= 0)
                            //双向绑定
                                xp.left = x;
                            else
							//双向绑定
                                xp.right = x;
                            root = balanceInsertion(root, x);
                            break;
                        }
                    }
                }
            }
            moveRootToFront(tab, root);
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值