HashMap就是这么简单【源码剖析】

小编 2026-06-30 阅读:208 评论:0
前言声明,本文用得是jdk1.8前面已经讲了Collection的总览和剖析List集合以及散列...

前言

声明,本文用得是jdk1.8

前面已经讲了Collection的总览和剖析List集合以及散列表、Map集合、红黑树的基础了:

本篇主要讲解HashMap,以及涉及到一些与hashtable的比较~

看这篇文章之前最好是有点数据结构的基础:

当然了,如果讲得有错的地方还请大家多多包涵并不吝在评论去指正~

一、HashMap剖析

首先看看HashMap的顶部注释说了些什么:

HashMap就是这么简单【源码剖析】

再来看看HashMap的类继承图:

HashMap就是这么简单【源码剖析】

下面我们来看一下HashMap的属性:

HashMap就是这么简单【源码剖析】

成员属性有这么几个:

HashMap就是这么简单【源码剖析】

再来看一下hashMap的一个内部类Node:

HashMap就是这么简单【源码剖析】

我们知道Hash的底层是散列表,而在Java中散列表的实现是通过数组+链表的~

再来简单看看put方法就可以印证我们的说法了:数组+链表-->散列表

HashMap就是这么简单【源码剖析】

我们可以简单总结出HashMap:

  • 无序,允许为null,非同步
  • 底层由散列表(哈希表)实现
  • 初始容量和装载因子对HashMap影响挺大的,设置小了不好,设置大了也不好

1.1HashMap构造方法

HashMap的构造方法有4个:

HashMap就是这么简单【源码剖析】

HashMap就是这么简单【源码剖析】

在上面的构造方法最后一行,我们会发现调用了tableSizeFor(),我们进去看看:

HashMap就是这么简单【源码剖析】

这是位运算算法,具体流程可参考:

看完上面可能会感到奇怪的是:为啥是将2的整数幂的数赋给threshold

  • threshold这个成员变量是阈值,决定了是否要将散列表再散列。它的值应该是:capacity * load factor才对的。

其实这里仅仅是一个初始化,当创建哈希表的时候,它会重新赋值的:

HashMap就是这么简单【源码剖析】

至于别的构造方法都差不多,这里我就不细讲了:

HashMap就是这么简单【源码剖析】

1.2put方法

put方法可以说是HashMap的核心,我们来看看:

HashMap就是这么简单【源码剖析】

我们来看看它是怎么计算哈希值的:

HashMap就是这么简单【源码剖析】

为什么要这样干呢??我们一般来说直接将key作为哈希值不就好了吗,做异或运算是干嘛用的??

我们看下来:

HashMap就是这么简单【源码剖析】

我们是根据key的哈希值来保存在散列表中的,我们表默认的初始容量是16,要放到散列表中,就是0-15的位置上。也就是tab[i = (n - 1) & hash]。可以发现的是:在做&运算的时候,仅仅是后4位有效~那如果我们key的哈希值高位变化很大,低位变化很小。直接拿过去做&运算,这就会导致计算出来的Hash值相同的很多。

而设计者将key的哈希值的高位也做了运算(与高16位做异或运算,使得在做&运算时,此时的低位实际上是高位与低位的结合),这就增加了随机性,减少了碰撞冲突的可能性!

下面我们再来看看流程是怎么样的:

HashMap就是这么简单【源码剖析】

新值覆盖旧值,返回旧值测试:

HashMap就是这么简单【源码剖析】

接下来我们看看resize()方法,在初始化的时候要调用这个方法,当散列表元素大于capacity * load factor的时候也是调用resize()

HashMap就是这么简单【源码剖析】

1.3get方法

HashMap就是这么简单【源码剖析】

接下来我们看看getNode()是怎么实现的:

HashMap就是这么简单【源码剖析】

1.4remove方法

HashMap就是这么简单【源码剖析】

再来看看removeNode()的实现:

HashMap就是这么简单【源码剖析】

二、HashMap与Hashtable对比

从存储结构和实现来讲基本上都是相同的。它和HashMap的最大的不同是它是线程安全的,另外它不允许key和value为null。Hashtable是个过时的集合类,不建议在新代码中使用,不需要线程安全的场合可以用HashMap替换,需要线程安全的场合可以用ConcurrentHashMap替换

HashMap就是这么简单【源码剖析】

Hashtable具体阅读源码可参考:

四、总结

在JDK8中HashMap的底层是:数组+链表(散列表)+红黑树

在散列表中有装载因子这么一个属性,当装载因子*初始容量小于散列表元素时,该散列表会再散列,扩容2倍!

装载因子的默认值是0.75,无论是初始大了还是初始小了对我们HashMap的性能都不好

  • 装载因子初始值大了,可以减少散列表再散列(扩容的次数),但同时会导致散列冲突的可能性变大(散列冲突也是耗性能的一个操作,要得操作链表(红黑树)
  • 装载因子初始值小了,可以减小散列冲突的可能性,但同时扩容的次数可能就会变多!

初始容量的默认值是16,它也一样,无论初始大了还是小了,对我们的HashMap都是有影响的:

  • 初始容量过大,那么遍历时我们的速度就会受影响~
  • 初始容量过小,散列表再散列(扩容的次数)可能就变得多,扩容也是一件非常耗费性能的一件事~

从源码上我们可以发现:HashMap并不是直接拿key的哈希值来用的,它会将key的哈希值的高16位进行异或操作,使得我们将元素放入哈希表的时候增加了一定的随机性

还要值得注意的是:并不是桶子上有8位元素的时候它就能变成红黑树,它得同时满足我们的散列表容量大于64才行的~

HashMap就是这么简单【源码剖析】

HashMap就是这么简单【源码剖析】


明天要是无意外的话,可能会写TreeMap,敬请期待哦~~~~

HashMap就是这么简单【源码剖析】

如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:Java3y。为了大家方便,刚新建了一下qq群:742919422,大家也可以去交流交流。
谢谢支持了!希望能多介绍给其他有需要的朋友

参考资料:

更多的文章可往:文章的目录导航
版权声明

本文仅代表作者观点,不代表百度立场。
本文系作者授权百度百家发表,未经许可,不得转载。

热门文章
  • 机房智能化温湿度解决方式之POE供电以太网温湿度传感器

    机房智能化温湿度解决方式之POE供电以太网温湿度传感器
    机房智能化温湿度解决方式之POE供电以太网温湿度传感器 北京盈创力和电子科技有限公司 智能型TCP网口温湿度记录仪 北京IP网络温湿度记录仪厂家,北京盈创力和 北京智能型TCP网口温湿度记录仪IP网络温湿度记录仪是一种新型的基于TCP/IP协议双绞线以太网标准温湿度采集模块,利用它可以实现现场温度值、相对湿度值的采集,同时利用其自身的RJ45通信接口可以方便地和机房监控主机或交换机集线器进行联网。 工作于-40℃~85℃工业级带...
  • Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering

    Sequential Monte Carlo Methods (SMC) 序列蒙特卡洛/粒子滤波/Bootstrap Filtering
    Problem Statement 我们考虑一个具有马尔可夫性质、非线性、非高斯的状态空间模型(State Space Model):对于一个时间序列上的观测结果{yt,t∈N}\\{ y_t , t \\in N \\}{yt​,t∈N},我们认为每个观测结果yty_tyt​的生成依赖于一个无法直接观察的隐变量xt∈{xt,t∈N}x_t \\in \\{x_t , t \\in N \\}xt​∈{xt​,t∈N},即:p(...
  • HTTP状态保持的原理

    HTTP状态保持的原理
    a)在用户登录之后,浏览器返回响应的时候会在响应中添加上cookieb)浏览器接收到cookie之后会自动保存c)当用户再次请求同一服务器中的其他网页的时候,浏览器会自动带上之前保存的cookied)服务接收到请求之后可以请 request 对象中取到cookie 判断当前用户是否登录  Http是无状态的,就是连接时数据互通,关闭后...
  • Hive 系统函数及示例

    Hive 系统函数及示例
    查看所有系统函数 show functions; 函数分类 内置函数【系统函数】 数学函数: floor、round、ceil、cos、log2等 字符串函数: length、reverse、trim、lower、get_json_object、repeat等 收集函数: size 转换函数: cast 日期函数: year、month、datediff、date、date_add等 条件函数: coalesce、case…w...
  • CSRF的原理和防范措施

    CSRF的原理和防范措施
    a)攻击原理:i.用户C访问正常网站A时进行登录,浏览器保存A的cookieii.用户C再访问攻击网站B,网站B上有某个隐藏的链接或者图片标签会自动请求网站A的URL地址,例如表单提交,传指定的参数iii.而攻击网站B在访问网站A的时候,浏览器会自动带上网站A的cookieiv.所以网站A在接收到请求之后可判断当前用户是登录状态,所以...
标签列表