Java集合之HashMap的数据结构分析

总所周知,Java中键值对集合,我们最常用的就是HashMap,那么它的数据结构,以及如何存储键值对,包括为什么使用红黑树,链表等许多数据结构,下面我们一起学习交流

1.HashMap的数据结构:

HashMap的数据结构采用:数组(哈希表)+链表+红黑树
1.数组(哈希表):
    HashMap内部定义了一个数组,数组中的每个位置被称为“桶”(Bucket),这是HashMap的基础结构【哈希表】;
    下标位置:当添加一个新的key-value 键值对时,会根据key的hashcode(),通过哈希函数(也叫哈希干扰函数)计算出一个新的哈希值 hash,并通过这个 hash值,计算key-value键值对在数组中的下标位置(桶,Bucket)
    数组容量:在添加第一个key-value键值对时,数组容量被初始化为16,并且可以根据key-value键值对的数量和负载因子(加载因子),数组会自动按照两倍扩容
2.链表:
    数组的每个位置(Bucket 桶)可以保存一个或多个key-value键值对
    当两个或更多的key-value键值对,被映射到数组的同一个位置(桶,bucket)时,就产生了哈希冲突
    HashMap使用链地址法,解决哈希冲突,这些键值对将以链表的形式存储在产生冲突的位置(桶,Bucket)

3.红黑树:
    为了优化链表的查询性能,当链表长度超过一个阈值(默认是8)并且数组的容量大于等于64时,链表会转换成红黑树
    红黑树是一种自平衡的二叉查找树,它可以基于二分查找的方式,进行元素的查找,提高查找性能,这对于较长的链表来说是一个明显的性能提升
    当红黑树中的节点数量减少到6各或更少时,红黑树转换回链表
   

.HashMap如何计算key-value键值对元素在数组中的存储位置:

为了时key-value元素可以均匀散列的保存在HashMap的数组中,所以使用key的哈希值进行哈希扰动函数计算出一个新的hash值
在JDK1.8版本之前,HashMap会将这个hash值与数组长度进行%模运算出一个下标,从而确定key-value在数组中的存储位置
    例如:数组长度默认为16,12580%16=4,753951%16=15,所以哈希值为12500,753951的键值对,会存储在数组下标为4和3的位置

在JDK1.8版本以后,由于% 模运算性能消耗比较大,所以采用(长度-1)&hash的位运算来计算存储位置
    例如:数组长度默认为16,(16-1)&12580=4,(16-1)&753951 ,所以哈希值为12580,753951的键值对,会继续存储在数组下标为4和3的位置。

HashMap的扩容机制?

HashMap的用来进行扩容的方法是resize();
HashMap在以下三种场景下,会触发扩容机制:
    1.当HashMap通过无参构造方法创建,在第一次调用put()方法添加key-value键值对时,数组初始化为16;
    2.当HashMap中的元素个数超过扩容阈值threshold时,数组的容量按照原容量的2倍进行扩容:
        扩容阈值threshold=数组容量×加载因子LoadFactor
        加载因子LoadFactor的默认值为0.75,数组容量默认为16,扩容阈值threshold默认值为12(16*0.75=12);
        所以,当HashMap中元素个数超过12时,数组的容量按照原容量的2倍进行扩容(16*2=32);
    3.加入元素时,如果链表长度大于阈值(默认为8)并且数组长度小于64,会产生数组扩容

HashMap为什么使用链表?

HashMap使用哈希表作为基础数据结构,当两个不同的key-value键值对,通过hash哈希值计算数组下标,出现像疼痛下标情况时,产生哈希冲突
HashMap使用”链地址法“解决哈希冲突,所以需要使用链表,来保存产生哈希冲突的key-value键值对

HashMap为什么使用红黑树?

HashMap中的链表长度增长到一定长度,会导致搜索性能下降(链表是线性方式搜索)
所以,HashMap会在链表过长,将链表转换为红黑树,通过红黑树提供搜索性能(红黑树是二分查找方式搜索)

HashMap不直接使用红黑树的原因:链表简单易于维护,红黑树维护复杂,所以首选使用链表,只有链表长度过长时,才会转换成红黑树来提高搜索查找的性能。

HashMap,LinkedHashMap,TreeMap的区别?

HashMap:无序,基于数组+链表+红黑树实现;
LinkedHashMap:有序,HashMap的子类
TreeMap:自动排序,按照key或者自定义Comparator比较器,进行排序

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

cph_507

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

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

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

打赏作者

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

抵扣说明:

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

余额充值