1.HashMap putVal 方法树结构解析
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/1bfb701e53da9bf9a3a08548aaba25b6.png)
// 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;
}
}
}