HashMap补充树结构部分

1.HashMap putVal 方法树结构解析

在这里插入图片描述

// map 创建的hashMap 本身 this  // tab 当前 的node<K,V>[]  哈希桶 哈希数组 h 哈希数值 需要put的key的hash值  K 我们的key本身 V 我们传入的内容

final TreeNode<K,V> putTreeVal(HashMap<K,V> map, Node<K,V>[] tab,
                                       int h, K k, V v) {
            Class<?> kc = null;
            boolean searched = false;
            //获取树的根节 如果父节
            TreeNode<K,V> root = (parent != null) ? root() : this;
            //从根节点开始遍历循环
            for (TreeNode<K,V> p = root;;) {
            // dir 元素存放位置  -1 在树的左侧 1 在右侧 ph当前节点元素哈希值  pk当前节点元素的 key  p是遍历的当前节点
                int dir, ph; K pk;
                //  将当前节点的哈希值 付给 ph  判断当前几点哈希值是否大于 传入的 hash值 大于放在树左侧 不大于 放在右侧
                if ((ph = p.hash) > h)
                    dir = -1;
                else if (ph < h)
                    dir = 1;
                    //  如果  节点的 hash值 等于我们传入的hash值 如果 我们现在节点上的 key地址和我们传入的一致 或者 k 不是null 并且和 我们的pk一致 返回节点
                else if ((pk = p.key) == k || (k != null && k.equals(pk)))
                    return p;
                    /**
			//下面的步骤主要就是当发生冲突 也就是hash相等的时候
			// 检验是否有hash相同 并且equals相同的节点。
			//  也就是检验该键是否存在与该树上
				//说明进入下面这个判断的条件是 hash相同 但是equal不同
				// 没有实现Comparable<C>接口或者 实现该接口 并且 k与pk Comparable比较结果相同              
				// comparableClassFor(Object x)方法,当x的类型为X,且X直接实现了Comparable接口(比较类型必须为X类本身)时,返回x的运行时类型;否则返回null。通过这个方法,我们可以搞清楚一些与类型、泛型相关的概念和方法。
				// compareComparables(kc, k, pk)  kc是我的key 对象的泛型  k 和 pk 是我的两个key  compareComparables() 方法为计算 k 和 pk 值的大小
				else if ((kc == null &&
                          (kc = comparableClassFor(k)) == null) ||
                         (dir = compareComparables(kc, k, pk)) == 0) {
//在左右子树递归的寻找 是否有key的hash相同  并且equals相同的节点
                    if (!searched) {
                        TreeNode<K,V> q, ch;
                        searched = true;
                        // 找到了 返回当前 节点
                        if (((ch = p.left) != null &&
                             (q = ch.find(h, k, kc)) != null) ||
                            ((ch = p.right) != null &&
                             (q = ch.find(h, k, kc)) != null))
                            return q;
                    }
                    没找到 说明是个新的 hash冲突值 计算 应该存放在树的哪个位置上
                    dir = tieBreakOrder(k, pk);
                }
				// x 保存当前节点 p找到树节点
                TreeNode<K,V> xp = p;
                // 如果 dir 是 小于 0 那么我获取 节点所在的树 左侧的子树 否则 获取 右侧的子树 
                // 如果 子树是null
                if ((p = (dir <= 0) ? p.left : p.right) == null) {
                    Node<K,V> xpn = xp.next;
                     //创建出一个新的节点
                    TreeNode<K,V> x = map.newTreeNode(h, k, v, xpn);
                    // 小于0 让当前节点的 左节点 存放新的节点
                    if (dir <= 0)
                        xp.left = x;
                    else
                        xp.right = x;
                        //维护双链表关系
                    xp.next = x;
                    x.parent = x.prev = xp;
                    //将root移到table数组的i 位置的第一个节点
                    //插入操作过红黑树之后 重新调整平衡。
                    if (xpn != null)
                        ((TreeNode<K,V>)xpn).prev = x;
                    moveRootToFront(tab, balanceInsertion(root, x));
                    return null;
                }
            }
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值