听说JDK源码难?一篇文章带你搞懂HashMap源码

JDK8之后HashMap的结构

在这里插入图片描述

  • JDK8之前,JDK以及更老版本,HashMap就是数组+链表
  • JDK8之后,HashMap为数组+链表+红黑树(冲突严重的链表会被"树化",将链表转为红黑树,提高冲突严重的链表的查询效率)

关于HashMap源码中属性的解读

在这里插入图片描述

在这里插入图片描述

put方法解读

在这里插入图片描述

hash方法

在这里插入图片描述
在这里插入图片描述

哈希函数设计理念:经过hash运算得到的值尽可能的平均

此时得到的值还不是当前数组的索引,只是经过hash运算得到的应该比较均衡的值

在这里插入图片描述

将上一步得到的key的hash值和当前哈希表长度-1进行&运算就可以得到索引值

相当于hash%数组长度(n)

注意:前提是n必须为2^n (初始化的哈希桶数量必须为2^n)

putVal方法

在这里插入图片描述

在这里插入图片描述

put方法核心流程小结

I.若HashMap还未初始化,先进行哈希表的初始化操作(默认初始化为16个桶)

II.对传入的key值做hash,得出要存放该元素的桶编号

​ a.若没有发生碰撞,即头结点为空,将该节点直接存放到桶中作为头结点

​ b.若发生碰撞

​ 1.此桶中的链表已经树化,将节点构造为树节点后加入红黑树

​ 2.链表还未树化,将节点作为链表的最后一个节点入链表

III.若哈希表中存在key值相同的元素,替换最新的value值

IV.若桶满了(rize++ 是否大于threshold),调用resize()扩容哈希表。 thresholed = 容量(默认16) * 负载因子 (默认0.75)

HashMap的构造方法

无参构造

在这里插入图片描述

构造时并没初始化数组

在这里插入图片描述

默认值为null

在这里插入图片描述

数组内部还没有初始化,只有第一次调用put方法时才初始化内部哈希桶数组。(懒加载模式)

第一次使用(添加)时才初始化相应的内存

有参构造

在这里插入图片描述

在这里插入图片描述

reszie()方法

既是扩容方法又是初始化方法,在resize()方法中进行哈希桶数组的初始化操作

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

Set集合和Map集合的关系

  • Set集合的子类实际上在存储元素时就是保存在Map集合的Key中,这也是Set元素不可重复的原因
  • HashSet可以保存Null,因为HashMap的Key可以为Null
  • TreeSet不能保存Null,因为TreeMap的key不能为Null

在这里插入图片描述

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值