【Java】HashMap原理-JDK1.7与JDK1.8的区别

2023-11-09

一、HashMap 扩容

JDK1.7 和JDK1.8 扩容原理相同

HashMap初始化大小为16, 负载因子为0.75,每次当容量大于16 * 0.75 时, 进行扩容,扩容为原来的两倍。也可以通过构造方法修改,但HashMap会自动将给定初始化大小扩容到2的幂次方。

  • JDK1.7: 扩容后需要重新计算hashcode值
  • JDK1.8:扩容后无需重新计算hashcode值。(具体看后面“HashMap的容量为2的幂次方”部分)

二、HashMap的冲突解决

JDK1.7以前

  • HashMap使用 数组 + 链表的方式来解决哈希冲突,并使用头插法
  • 使用头插法的原因:一般情况下,新加入的键值对被查找访问的概率更高。 当链表长度大于阈值(默认为8)时,就会对数组进行扩容。

JDK1.8以后

  • HashMap使用 数组 + 链表 + 红黑树的方式来解决哈希冲突,并使用尾插法
  • 当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。
  • 使用尾插法的原因:因为尾插法可以统计链表长度,判断是否大于8,而且链表过长时会转化为红黑树,所以时间浪费不高。
  • 使用红黑树的原因:相比于平衡二叉排序树,红黑树只有在最长路径>最短路径*2时才触发旋转操作。红黑树的查找删除时间复杂度为O(logn)。

补充:将链表转为红黑树前会判断,如果当前数组的长度小于64,那么会选择先进行数组扩容,而不是转换为红黑树。

三、为什么HashMap的容量为2的幂次方

(1)为了找到key的位置在哈希表的哪个槽里,需要计算hash(KEY) % length。若使length为2的幂次方,可以将取余操作变为hash(KEY) & (length - 1),将取余操作变换为位运算从而提高运算的效率。

举例说明

可以看下这个例子,这个例子来自灰信网
假如array.length = 2^4 = 16,二进制10000。这个数减去1的结果是1111,也就是array.length -1 = 1111。
再假设一个key的hashCode值为10011011001,与1111做 & 操作,得到的结果是1001(高位部分1001101都舍去了)。而1001(二进制)必然是一个小于10000(数组长度二进制)的数,对于一个小于10000(数组长度二进制)的数而言,1001 % 10000得到的就是1001(二进制)自己。
那么刚刚舍弃的高位部分1001101 0000(后面补上了四个0000)就一定能被10000整除吗?答案是肯定的:因为10011010000可以拆成10000000000+10000000+1000000+10000,这几个数都能通过10000的n次左移得到,也就相当于这几个数都能被10000整除。那他们的和,也就是10011010000,一定也可以被10000整除。
因此,最终结论就是:10011011001 & ( 10000 - 1 ) = 10011011001 & 1111 = 1001 = 10011011001 % 10000

(2)进行扩容时,需要移动的数据较少。每次扩容相当于数组长度的高位多一个1,新的hash运算取决于hashcode在这一位上的值是0还是1,是0则无需变换位置,是1则位置为原来位置+原来数组长度 的位置。

举例说明

例如,原来长度为16,扩容后为32。则16-1的二进制为0000 1111,32-1的二进制为0001 1111。
假设一个KEY通过哈希函数计算得到的哈希值为52(二进制为0011 0100),在扩容前 将0011 0100与0000 1111进行与运算,结果为0000 0100。扩容后,将0011 0100与0001 1111进行与运算,结果为 0001 0100。
扩容后相当于高位多了个1,根据与运算的特性,只有在原哈希值在这一位上为1时,最后与运算的结果也为1。
因为扩容后最高位肯定会变为1,所以只要判断原哈希值这一位上是0还是1就可以决定扩容后是否要移位。如果是0,扩容前后与运算的结果一样,则表示新位置与旧位置相同,不需要移位。如果为1,则要移位。
那移动到的新位置其实就是高位多个1,也就等价于在原来的位置上加上原数组长度的位置。
这个例子的详细图解可以看jdk8之HashMap resize方法详解(深入讲解为什么1.8中扩容后的元素新位置为原位置+原数组长度

本文参考如下链接:

通俗易懂HASHMAP为何喜欢2的倍数扩容,(数组容量是2的次幂)

jdk8之HashMap resize方法详解(深入讲解为什么1.8中扩容后的元素新位置为原位置+原数组长度)
HashMap底层为什么是2倍扩容?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Java】HashMap原理-JDK1.7与JDK1.8的区别 的相关文章

  • Java Swing:从 JOptionPane 获取文本值

    我想创建一个用于 POS 系统的新窗口 用户输入的是客户拥有的金额 并且窗口必须显示兑换金额 我是新来的JOptionPane功能 我一直在使用JAVAFX并且它是不同的 这是我的代码 public static void main Str
  • 为什么 i++ 不是原子的?

    Why is i Java 中不是原子的 为了更深入地了解 Java 我尝试计算线程中循环的执行频率 所以我用了一个 private static int total 0 在主课中 我有两个线程 主题 1 打印System out prin
  • 如何找到给定字符串的最长重复子串

    我是java新手 我被分配寻找字符串的最长子字符串 我在网上研究 似乎解决这个问题的好方法是实现后缀树 请告诉我如何做到这一点或者您是否有任何其他解决方案 请记住 这应该是在 Java 知识水平较低的情况下完成的 提前致谢 附 测试仪字符串
  • 制作一个交互式Windows服务

    我希望我的 Java 应用程序成为交互式 Windows 服务 用户登录时具有 GUI 的 Windows 服务 我搜索了这个 我发现这样做的方法是有两个程序 第一个是服务 第二个是 GUI 程序并使它们进行通信 服务将从 GUI 程序获取
  • 无法展开 RemoteViews - 错误通知

    最近 我收到越来越多的用户收到 RemoteServiceException 错误的报告 我每次给出的堆栈跟踪如下 android app RemoteServiceException Bad notification posted fro
  • 操作错误不会显示在 JSP 上

    我尝试在 Action 类中添加操作错误并将其打印在 JSP 页面上 当发生异常时 它将进入 catch 块并在控制台中打印 插入异常时出错 请联系管理员 在 catch 块中 我添加了它addActionError 我尝试在jsp页面中打
  • 斯坦福 NLP - 处理文件列表时 OpenIE 内存不足

    我正在尝试使用斯坦福 CoreNLP 中的 OpenIE 工具从多个文件中提取信息 当多个文件 而不是一个 传递到输入时 它会给出内存不足错误 All files have been queued awaiting termination
  • 在两个活动之间传输数据[重复]

    这个问题在这里已经有答案了 我正在尝试在两个不同的活动之间发送和接收数据 我在这个网站上看到了一些其他问题 但没有任何问题涉及保留头等舱的状态 例如 如果我想从 A 类发送一个整数 X 到 B 类 然后对整数 X 进行一些操作 然后将其发送
  • 为什么HashMap不能保证map的顺序随着时间的推移保持不变

    我在这里阅读有关 Hashmap 和 Hashtable 之间的区别 http javarevisited blogspot sg 2010 10 difference Between hashmap and html http javar
  • JRE 系统库 [WebSphere v6.1 JRE](未绑定)

    将项目导入 Eclipse 后 我的构建路径中出现以下错误 JRE System Library WebSphere v6 1 JRE unbound 谁知道怎么修它 右键单击项目 特性 gt Java 构建路径 gt 图书馆 gt JRE
  • getResourceAsStream() 可以找到 jar 文件之外的文件吗?

    我正在开发一个应用程序 该应用程序使用一个加载配置文件的库 InputStream in getClass getResourceAsStream resource 然后我的应用程序打包在一个 jar文件 如果resource是在里面 ja
  • 总是使用 Final?

    我读过 将某些东西做成最终的 然后在循环中使用它会带来更好的性能 但这对一切都有好处吗 我有很多地方没有循环 但我将 Final 添加到局部变量中 它会使速度变慢还是仍然很好 还有一些地方我有一个全局变量final 例如android Pa
  • 加密 JBoss 配置中的敏感信息

    JBoss 中的标准数据源配置要求数据库用户的用户名和密码位于 xxx ds xml 文件中 如果我将数据源定义为 c3p0 mbean 我会遇到同样的问题 是否有标准方法来加密用户和密码 保存密钥的好地方是什么 这当然也与 tomcat
  • AWS 无法从 START_OBJECT 中反序列化 java.lang.String 实例

    我创建了一个 Lambda 函数 我想在 API 网关的帮助下通过 URL 访问它 我已经把一切都设置好了 我还创建了一个application jsonAPI Gateway 中的正文映射模板如下所示 input input params
  • Eclipse Java 远程调试器通过 VPN 速度极慢

    我有时被迫离开办公室工作 这意味着我需要通过 VPN 进入我的实验室 我注意到在这种情况下使用 Eclipse 进行远程调试速度非常慢 速度慢到调试器需要 5 7 分钟才能连接到远程 jvm 连接后 每次单步执行断点 行可能需要 20 30
  • 如何在桌面浏览器上使用 webdriver 移动网络

    我正在使用 selenium webdriver 进行 AUT 被测应用程序 的功能测试自动化 AUT 是响应式网络 我几乎完成了桌面浏览器的不同测试用例 现在 相同的测试用例也适用于移动浏览器 因为可以从移动浏览器访问 AUT 由于它是响
  • 玩!框架:运行“h2-browser”可以运行,但网页不可用

    当我运行命令时activator h2 browser它会使用以下 url 打开浏览器 192 168 1 17 8082 但我得到 使用 Chrome 此网页无法使用 奇怪的是它以前确实有效 从那时起我唯一改变的是JAVA OPTS以启用
  • 有没有办法为Java的字符集名称添加别名

    我收到一个异常 埋藏在第 3 方库中 消息如下 java io UnsupportedEncodingException BIG 5 我认为发生这种情况是因为 Java 没有定义这个名称java nio charset Charset Ch
  • JGit 检查分支是否已签出

    我正在使用 JGit 开发一个项目 我设法删除了一个分支 但我还想检查该分支是否已签出 我发现了一个变量CheckoutCommand但它是私有的 private boolean isCheckoutIndex return startCo
  • java.lang.IllegalStateException:驱动程序可执行文件的路径必须由 webdriver.chrome.driver 系统属性设置 - Similiar 不回答

    尝试学习 Selenium 我打开了类似的问题 但似乎没有任何帮助 我的代码 package seleniumPractice import org openqa selenium WebDriver import org openqa s

随机推荐

  • 【毕设教程】随机森林算法

    文章目录 0 前言 1 什么是随机森林 2 随机森林构造流程 3 随机森林的优缺点 3 1 优点 3 2 缺点 3 3 随机森林算法实现 4 最后 0 前言 Hi 大家好 这里是丹成学长的毕设系列文章 对毕设有任何疑问都可以问学长哦 这两年
  • Firebug调试经验与技巧

    昨天网站出问题了1 为了调试cookie 特别找了关于firebug里面如何调试cookie的文章 觉得这篇不错 保留下来备份 Firebug调试经验与技巧 2009 03 13 15 22 16 转自 http blog sina com
  • redis,mysql,elasticsearch,hbase,hive对比区别,该如何选择

    几种数据库对比如下 redis mysql elasticsearch hbase hive 容量 容量扩展 低 中 大 海量 海量 查询时效性 极高 中等 较高 较高 低 查询灵活性 较差 非常好 较好 较差 非常好 写入速度 极快 中等
  • U3D通过按钮点击实现场景切换

    1 新建UI 选择button选项 新建button 2 file gt Build settings gt Add Open Scenes 把你当前场景添加进去 gt 把你想要切换的场景拖拽上去 3 新建一个空对象 挂载一个scenech
  • org.apache.http.ConnectionClosedException Premature end of Content-Length delimited message body

    最近生产环境报了这个系统异常 org apache http ConnectionClosedException Premature end of Content Length delimited message body expected
  • CANOE入门:DBC创建和编辑

    目录 dbc文件创建步骤 创建一个DBC数据库文件 创建网络节点Network nodes 创建Message 创建信号Signal 创建Signals用到的数值表Value Tables 将Value Tables关联到Signals 将
  • I/O error on GET request for "http://user-service/hi": user-service; nested exception is java.net.Un

    一 场景重现 最近闲暇时间打算系统学习下SpringCloud系统教程 毕竟最近微服务也挺火的 于是网上找了一个大牛的博客跟着一起学习 史上最简单的SpringCloud教程 一直跟着模仿构建SpringCloud一直也没出什么问题 直到在
  • Pgsql与Oracle语法差异(SQL迁移记录)

    oracle 数据库中没有limit关键字 LIMIT 1 替换为 rownum 1 select from table where rownum 1 输出1条 oracle 自增序列使用 sequence PGSQL 自增序列可用 ser
  • jquery笔记回顾

    jquery 1 jquery概念 js框架封装的原生的js代码 2 jquery版本区别及使用 jquery xxx js 有排版 体积大 jquery xxx min js 无排版 体积小 3 jquery与原生js对象进行互转 jqu
  • hk-bc.xyz forum.php,www.xavdz.com

    Domain Name XAVDZ COM Registry Domain ID 1838157110 DOMAIN COM VRSN Registrar WHOIS Server whois enom com Registrar URL
  • Kafka面试题

    Kafka核心总控制器Controller是什么 在Kafka集群中会有一个或者多个broker 其中有一个broker会被选举为控制器 Kafka Controller 它负责管理整个集群中所有分区和副本的状态 Controller选举机
  • 使用代理同步Chromium代码的心得

    先参看 http www chromium org developers how tos build instructions windows 非常坑爹 谷歌获取chromium源码的方式又变了 从chromium39 0 2313 2之后
  • poj 2155 Matrix

    Problem poj org problem id 2155 vjudge net contest 146952 problem A Meaning 一个 N N 的矩阵 A 初始时全部值为 0 有两种操作 1 C x1 y1 x2 y2
  • 电机驱动板发烫严重怎么办?一份大厂PCB布局指南参考

    作者 Pete Millett Technical Marketing Engineer Monolithic Power Systems 翻译 Toffee Jia 来源 MPS 电机驱动 IC 传递大量电流的同时也耗散了大量电能 通常
  • java远程连接linux并发送命令,两种方案比较Jsch与ganymed-ssh2

    通过Jsch连接 step 1引入jar包
  • curl学习2

    代理 什么是代理 Merrian Webster的解释是 一个通过验证的用户扮演另一个用户 今天 代理已经被广泛的使用 许多公司提供网络代理服务器 允许员工的网络客户端访问 下载文件 代理服务器处理这些用户的请求 libcurl支持SOCK
  • 滑动穿透终极解决方案

    问题描述 滑动穿透 浮层上的触控会导致底层元素滑动 问题探究 1 给body加overflow hidden pc端可以锁scroll 移动端无效 pc端可以直接overflow hidden解决 2 给body加overflow hidd
  • 数据结构学习系列之单向链表的去重

    单向链表的去重 所谓的去重 就是去除单向链表中重复的数据结点 代码如下 示例代码 int del rep link list node t phead if NULL phead printf 入参为NULL 请检查 n return 1
  • 云计算通俗解释,什么叫云计算

    计算已经越来越为大众所熟知 那么云计算到底是什么呢 有没有云计算通俗解释呢 云计算是由分布式计算 并行处理 网格计算发展来的 是一种新兴的商业计算模型 目前 对于云计算的认识在不断的发展变化 云计算仍没有普遍一致的定义 云计算 Cloud
  • 【Java】HashMap原理-JDK1.7与JDK1.8的区别

    一 HashMap 扩容 JDK1 7 和JDK1 8 扩容原理相同 HashMap初始化大小为16 负载因子为0 75 每次当容量大于16 0 75 时 进行扩容 扩容为原来的两倍 也可以通过构造方法修改 但HashMap会自动将给定初始