java源码系列:HashMap源码验证,在JDK8中新增红黑树详解

红黑树查询演示,红黑树它解决了链表查询过慢的问题

我们插入的链表过长之后,因为我们的链表都是从头部开始进行查询,所以它会比较慢。

我们现在引入到我们的红黑树之后呢,它就不会有这个问题,那它是怎么去解决呢?

同学们,我们来看一看,刚才我们还是去插入这7个元素

那同学们,我们一个红黑树的,它的一个结构呢,就七个节点的元素是这样的,

来我们看一下,我们用红黑树去查这个007要查多少次呢?

一次,两次,三次,四次,

同学们,也就是说我们用红黑树啊,只要查四次,而刚才我这个用链表是要查七次,

那我是不是减少了三次的这个查询次数,那同时我们就非常的明显,

如果我们这边是70万,这边只要查40万,那我就减少了30万的查询,

那这样的话是不是性能将近提高了一倍,能理解吧,

所以我们这个红黑树,它就是去解决我们链表查询过慢的一个问题。

数据结构可视化网址

Red/Black Tree Visualization (usfca.edu)

在JDK8里面,HashMap并不是一上来就直接用这个红黑树

但是呢,我们这个HashMap,在JDK8里面,它并不是一上来就直接用这个红黑树,

一上来它默认还是先用链表,只有当我们的这个链表达到一个阈值的情况下,

它才会用这个红黑树,那你们知道这个阈值是多少吗?

阈值是8,那同学们我想问一下,为什么是8呢?

看HashMap源码

咱们看这个HashMap的一个源码,Shift+Shift,搜索HashMap,

同时勾选 Include non-project items,如下图

在这个地方,HashMap呢,我们主要看它的这个put方法,它调用了 putVal方法,

那这个 putVal 方法里面呢,它有一个值,这个条件它就等于8,

那为什么我们的链表的长度大于8之后呢,就会用红黑树,

如果不大于8的话,它是用链表,大家你们知道为什么吗?

来,其实在这里,它也不是等于8,严格意义上它是用8减1,

if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st

大家看它的条件,你看如果这个条件满足情况,它就调这个方法 treeifyBin,

                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;

treeifyBin 这个方法,

你看一上来的话,它这里是用什么?这里是用的是咱们这个链表,

你看里面有 hash(哈希),有 key 和 value,next 对吧?开始用链表,

但是当我们这个条件执行 else if 的时候,他用这个 TreeNode,

而这个 TreeNode  就是咱们这个红黑树,你看里面,还有 boolean 类型是否为红节点,

我们的上一个节点、右节点、左节点,还有我们的根节点,

为什么红黑树查询快,插入慢?

为什么红黑树,它的查询性能就一定会比咱们的这个链表快呢?

第一个就取决于它这个查询的规律不一样对吧!

那么我想问一下,那为什么就一定要有一个阈值?为什么还要先要用链表的?

那为什么一上来不直接用红黑树呢?原因是什么?

而且我们明明已经知道链表,它已经会带来这个查询的这个慢的原因

我们要知其然知其所以然,那么这个东西呢,其实就是鱼和熊掌不可兼得,

那我来跟大家去讲一下,刚刚在这个地方,我是讲的是红黑素这个查询,但是同学们,

我来给大家看一下它的插入,它的插入你来认真去看这个节点,你就明白了!

来我把这个东西给你再演示一遍

你们注意看啊,插入第一个,插入第二个

好,当我去插第三个值的时候,你们注意看啊,看到没有,

我们的这个001,它进行了一次左移(左旋)。

也就是说我们的红黑树,它的查询是比较快,但是它的插入比较慢,为什么呢?

因为它需要对我们的值进行左移,进行左移(左旋)的话,他们的数据是进行需要进行交换的,

所以在这个过程中,我可以很负责任的告诉大家,我们的这个插入,

我们的链表绝对会比我们的红黑树要更快一些。

所以我们来看一看链表它的特性是什么?它的特性是插入删除会比较快,

因为它只要O(1)的操作,而咱们这个红黑树很明显不是O(1)的操作,

所以这就是为什么需要有一个阈值,这个阈值就是使得它们两者达到一个平衡。

这就是鱼和熊掌不可兼得!

那在这里我就跟大家讲,为什么我们的红黑树,它查询为什么会快呢?原因你们知道为什么吗?

因为我们的红黑树,它需要维护一个结构,维护一个什么样的结构呢?

我把这个技巧告诉大家,这个技巧就是:小中大,左中右

那这个是一个什么样的一个结构呢?

那大家我们来看啊,当前我这个红黑树数的一个节点,根节点是002,

我们要去查询的这个值是007,而比002小的是不是001。

你看比它002小的,是不是在左边,比002大的,你看003、004、005、006、007都在右边,

大家能理解这个点吗?这就是小中大,左中右这个结构,

你任何一个节点的数据都是这样的。

来我们来看004啊,你看004也是一样,比004小的,都在左边,

你看001、002、003是不是都在左边。

比004大的,是不是在右边,你看005、006、007。

同样,006也是一样,这就是小中大,左中右这个结构,

如果你能理解这个点,那你就明白了,所以为什么我们的红黑素在插入的时候会慢,

因为它要维护这样的一个结构,它要维护一个小中大,左中右的一个结构,

所以我们为什么查007的话,为什么快?

因为我们首先呢,007跟002进行比较对吧,所以发现这个007大

就这样,007依次会002、004、006、007 进行比较,直到找到相等的007

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

被开发耽误的大厨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值