jdk1.8-hashmap 树化过程

本文详细探讨了JDK1.8中HashMap的树化过程,包括触发树化的条件(节点数超过8个),以及树化步骤:转换为双向链表,再逐个插入到红黑树中,确保红黑树的根节点成为双向链表的头结点。同时阐述了树化过程中对红黑树和双向链表同步维护的重要性。
摘要由CSDN通过智能技术生成

在jdk8中的hashmap,引入了红黑树的概念,那自然就会涉及到树化的过程,这篇笔记单独记录下树化的一些细节

结论

1、在达到树化的要求之后,会将当前单向链表转换为双向链表存储
2、然后从头到尾,依次拿着双向链表的节点,向红黑树中put
3、在put的过程中,可能会发生root节点的转换,也就是树的平衡,那如果root节点变化了之后,同时,会把新的root节点对应的元素,从双向链表中,移到头结点
4、所以,在hashmap中,一个红黑树,对应着一个双向链表,双向链表的头结点,永远是红黑树的root节点,在红黑树新增或者删除元素的时候,需要同步维护最新的root节点到双向链表的头结点

树化的条件


for (int binCount = 0; ; ++binCount) {
   
    //这里是遍历到链表的最后一个
    if ((e = p.next) == null) {
   
        p.next = newNode(hash, key, value, null);
        /**
         * 这里这个树化阈值的判断需要仔细琢磨一下
         * 如果当前链表有八个节点,刚刚将newNode插入到了尾结点后面,也就是说
         * 此时的newNode是链表中的第九个节点,此时才会进行树化
         * 因为bitCount是从0开始的,也就是说bitCount为7的时候,才会树化,此时已经有了八个节点
         * newNode再插进来,当然是第九个了
         */
        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
            treeifyBin(tab, hash);
        break;
    }
    /**
     * 在遍历的过程中,如果找到相同的key,就退出遍历,进行覆盖
     * 但是不是在这里覆盖, 在下面判断中进行的覆盖
     * 可以整体看下这里的逻辑,如果进入到下面的if判断中,那此时就会中断for循环,这时 e != null
     * 如果这里的if判断一直没有进去,那就会进入到上面 if((e = p.next) == null)的判断,也就是说,e == null
     */
    if (e.hash == hash &&
        ((k = e.key) == key || (key != null && key.equals(k))))
        break;
    p = e;
}

这是put方法中的部分代码,在当前插入的元素大于8个时,会进行树化

树化的过程

/**
 * 链表转换红黑树,进行树化的目的是将链表中节点的查询效率提高
 * 1.需要满足两个条件:数组不为空且hashmap数组的长度超过64,否则,只会进行扩容,不会进行树化
 *  如果数组长度不超过64,就可以进行扩容,因为扩容之后,链表的长度就会变为一半
 * 2.e表示的是数组中某个链表对应的头结点
 *   2.1 do while循环,会把链表中每个node节点进行转换,转换成treeNode,然后将链表变成了双向链表,有prev和next,hd表示的是原链表的第一个节点,
 *   2.2 然后根据hd进行真正的红黑树转换,hd就是红黑树初始化的根节点
 *
 * 所以:链表转红黑树,首先会把当前的单向链表,转换成双向链表,然后再拿着双向链表的头结点hd去进行红黑树的转换
 *
 * @param tab
 * @param hash:待插入元素key值对应的hash
 */
final void treeifyBin(Node<K,V>[] tab, int hash) {
   
    int n, index; Node<K,V> e;
    if (tab == null 
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值