经典数据结构之HashMap

每日学习一丢丢,登顶就在眼前

HashMap是开发中使用非常频繁的键值对形式的工具类,主要是用起来十分方便,但是需要注意的是HashMap他不是线程安全的哦,多线程场景下可以使用ConcurrentHashMap🔍,面试中经常会提到HashTable,但是已经过时了的一个工具,虽说线程安全但是性能低下,HashMap从Java 8开始,源码做了一定的修改,以此来提升其性能;

以上是HashMap的一个数据结构:整体上可以看作是数组+链表的形式。数组是为了快速检索,如果hash函数冲突了的话,就会在同一位置后面进行挂链表的操作。也就是说,同一个链表上的节点,他们的hash值计算出来是一样的。但是如果hash冲突比较多的时候,生成的链表也会拉得比较长,这个时候检索起来就会退化成便利操作,性能就比较低了,在Java 8中为了改善这种情况,引入了红黑树。

红黑树是一种高级的平衡二叉树,其能保证查找、插入、删除的时间复杂度最坏为0(logn)。在大数据量的场景下,相比于AVL树,红黑树的插入删除性能要更高。当链表中的节点数量大于等于8的时候,同时当前数组中的长度大于等于MIN_TREEIFY_CAPACITY时,链表中的所有节点会被转化成红黑树,而如果当前链表节点的数量小于等于6的时候,红黑树又会被退化成链表。

其中MIN_TREEIFY_CAPACITY的值为64,也就是说当前数组中的长度(也就是桶bin的个数)必须大于等于64的时候,同时当前这个链表的长度大于等于8的时候,才能转化。如果当前数组中的长度小于64,即使当前链表的长度已经大于8了,也不会转化

那么为什么不直接用红黑树来代替链表,而是采用链表和红黑树来搭配在一起使用呢?

原因就在于红黑树虽然性能更好,但是这也仅是在大数据量下才能看到差异。如果当前数据量很小,就几个节点的话,那么此时显然用链表的方式会更划算。因为要知道红黑树的插入和删除操作会涉及到大量的自旋,以此来保证树结构的平衡。如果数据量小的话,插入删除的性能高效根本抵消不了自旋操作所带来的成本。

还有一点需要留意的是链表转为红黑树的阈值是8,而红黑树退化成链表的阈值是6。为什么这两个值会不一样呢?

可以试想一下,如果这两个值都为8的话,而当前链表的节点数量为7,此时一个新的节点进来了,计算出hash值和这七个节点的hash值相同,即发生了hash冲突。于是就会把这个节点挂在第七个节点的后面,但是此时已经达到了变成红黑树的阈值了(MIN_TREEIFY_CAPACITY条件假定也满足),于是就转成红黑树
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值