HashMap实现原理

目录

HashMap原理

hashmap的put流程:

HashMap扩容机制:

HashMap的寻址算法:

HashMap原理

HashMap的底层数据结构是由,数组,链表和红黑树组成的。

当我们往HashMap中put元素的时候,利用key的hashCode重新计算hash出当前对象的元素在数组中的下标。

当然这样也可能会出现一个问题,如果出现hash值相同的key,那么如何进行处理呢?有的人可能会问,哈希值怎么可能相同,那么此时我们需要明白一个道理,很简单,鸽巢原理:可以概括为一句话,假如我们有10个鸽巢,11个鸽子,那么此时必定至少有一个鸽巢内的鸽子数是大于两个的。应用到Hashmap中,如果存储的Key的数量大于数组的原始长度,势必会存在hash值相同的key。那么此时就需要引入链表了。

在解决上述问题时,HashMap给出了链表的结构来进行存储,如果出现hash值相同的key,那么此时会出现两种情况。

1.如果key相同,则覆盖原始key对应的value;

2.如果key不同,那么就将当前的key-value放入到链表(尾插法)或者红黑树中;

在获取时,会直接找到hash对应的下标,再进一步判断key值是否相同,从而找到对应值。

JDK1.8在解决hash冲突时,当链表长度大于阈值时,并且数组长度达到64,就会将链表转成红黑树,以较少搜索时间。扩容resize()时,红黑树拆分成的树节点小于等于临界值6时,则退化成链表。

hashMap默认的加载因子为0.75,默认的初始容量为16.当存储的阈值为大于16*0.75时会自动进行扩容

hashmap的put流程:

可以分为以下几步:

1.会判断table是否为空,如果为空,则代表是第一次进行创建,于是会初始化一个长度为16的数组

2.然后根据你的key计算索引值,如果该索引位置为null,那么就直接插入,否则就去判断该key是否存在在该位置。

3.如果是存在,那么直接覆盖,如果不存在,那么就会判断该位置是否为红黑树,走红黑树的添加逻辑。

4.如果不是红黑树,那么就说明此处是一个链表,那么就遍历该链表,判断key是否存在在该链表之中,如果存在直接覆盖。

5.如果不存在,那么会在链表尾部进行插入,此时还需判断链表是否长度大于8,如果大于则转成红黑树,否则直接返回。

6.插入完成之后还会判断整个table的size是否大于扩容的阈值,如果大于的话,就会对hashmap进行扩容。

HashMap扩容机制:

1.首先会判断你的capacity是否是大于0的如果不大于0说明你是第一次来,那么就进行设置数组容量为16,负载因子为0.75,阈值为12.

2.如果不是第一次来,那么就会将hashmap大小设置为两倍的capacity,然后去新建数组,此时他会去遍历旧的数组,对原来链表里的key重新进行添加。

3.如果该位置为空,那么直接就添加,

4.如果该位置为红黑树,那么就是红黑树的添加逻辑。

5.如果该位置为链表,那么就会遍历链表,然后让新的hash值和原来的链表长度按位与,如果值为0那么新表的位置也为原来的位置,否则就是原来的位置加原来的数组容量,比如原来是3位置存储,大小为16,那么新的位置就是19。

HashMap的寻址算法:

1.计算对象的hashcode

2.调用hash()方法二次哈希,hashcode右移16位再异或运算,让哈希分布更均匀。

3.再使用(capacity-1)& oldcapacity得到索引。

使用2的n次方作为哈希的数组长度,可以代替取模运算,效率更高。

另一个原因就是,如果计算索引的时候,可以让hash& oldcap == 0 的值留在原来的位置,否则让新位置=旧位置+oldcap。

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值