前提:
- jdk1.8之前HashMap的存储方式:链表+hash
- jdk1.8以后中HashMap的存储方式:链表+hash+红黑树算法
作用
- 根据key查找原HashMap中存在的对象,如果有冲突的key,则返回与之冲突的key的对象
- 如果没有冲突的key,则直接存放当前对象,并树化结构,并重置根节点,保持二叉树平衡
业务逻辑整理
- 1,获取根节点
- 2,遍历table数组的树结构
- 2.1,查找是否与key冲突的对象,如果有则返回当前对象
- 2.2,如果没有冲突,则识别key应该存放的位置(设置dir的值)
- 2.3,根据key,value创建对象,并根据dir的值,设置当前对象存放位置
- 2.4,树化整个结构(设置各个节点的是否为红色节点,是否需要左旋,右旋)
- 2.6,重置根节点,保持红黑树平衡
源码分析
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;;) {
int dir, ph; K pk;
if ((ph = p.hash) > h)
dir = -1;
else if (ph < h)
dir = 1;
else if ((pk = p.key) == k || (k != null && k.equals(pk)))
return p;
else if ((kc == null &&
(kc = comparableClassFor(k)) == null) ||
(dir = compareComparables(kc, k, pk)) == 0) {
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;
}
dir = tieBreakOrder(k, pk);
}
TreeNode<K,V> xp = p;
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);
if (dir <= 0)
xp.left = x;
else
xp.right = x;
xp.next = x;
x.parent = x.prev = xp;
if (xpn != null)
((TreeNode<K,V>)xpn).prev = x;
moveRootToFront(tab, balanceInsertion(root, x));
return null;
}
}
}