【Java基础】HashMap 原理

文章目录

    • 1、HashMap 设置值的原理
    • 2、HashMap 获取值原理
    • 3、HashMap Hash优化
    • 4、HashMap 寻址优化
    • 5、HashMap 是如何解决Hash冲突的?
      • 5.1 get数据的时候,如果定位到指定位置的元素是一个链表,怎么办呢?
      • 5.2 红黑树
    • 6、数组扩容
      • 6.1 数组长度为16,计算index
      • 6.2 数组长度为32, 计算index
      • 6.3 扩容总结:

1、HashMap 设置值的原理

  1. 根据key计算HashCode,
  2. 再使用HashCode对 数组长度取模,结果一定是存放到数组中 的某一个位置。
  3. 得到指定位置索引之后,就往指定位置设置数据即可。

2、HashMap 获取值原理

  1. 根据key计算hashCode,
  2. 再使用hashCode对 数据长度取模,得到一个数组索引,
  3. 然后再根据索引从数组中获取指定数据即可。

3、HashMap Hash优化

      // JDK 1.8以后的HashMap里面的一段源码static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

答案:hash数组一般不会太大,使用 key 的hashCode 和 key的hashCode 右移16位 进行异或运算的目的就是让 高低16位都参与运算,减少hash冲突

4、HashMap 寻址优化

hash & (n - 1)

当n为2的n次方的时候, hash & (n - 1) = hash % n

答案:hash & (n - 1) -> 效果是跟hash对n取模,效果是一样的,但是与运算的性能要比hash对n取模要高很多,数学问题,数组的长度会一直是2的n次方,只要他保持数组长度是2的n次方

5、HashMap 是如何解决Hash冲突的?

使用链表法解决。
在数据的指定位置,挂一个链表,这个链表里放多个元素,让多个 key-value 放在数据的同一个位置

5.1 get数据的时候,如果定位到指定位置的元素是一个链表,怎么办呢?

get 的时候,如果定位到数组发现这个位置挂了一个链表哦,此时就会遍历 链表,从链表里面选择到自己需要的那个 kye-value 就可以了。

5.2 红黑树

为了解决hash冲突的问题,就会在 数据的指定为值挂一个链表,如果链表的长度达到了一定的长度之后,就会将链表转换成红黑树,通过遍历一颗红黑树找到一个元素,此时时间复杂度是 O(logn), 性能比链表要高一些。
如果链表过长,遍历的性能不高,因此当链表长度超过一定限制的时候,就会将链表转换成红黑树,提升搜索性能。

6、数组扩容

6.1 数组长度为16,计算index

n - 1  0000 0000 0000 0000 0000 0000 0000 1111
hash1  1111 1111 1111 1111 0000 1111 0000 0101
&      0000 0000 0000 0000 0000 0000 0000 0101 = 5(index = 5的位置)n - 1  0000 0000 0000 0000 0000 0000 0000 1111
hash2  1111 1111 1111 1111 0000 1111 0001 0101
&      0000 0000 0000 0000 0000 0000 0000 0101 = 5(index = 5的位置)

6.2 数组长度为32, 计算index

n-1    0000 0000 0000 0000 0000 0000 0001 1111
hash1  1111 1111 1111 1111 0000 1111 0000 0101
&结果   0000 0000 0000 0000 0000 0000 0000 0101 = 5(index = 5的位置)n-1    0000 0000 0000 0000 0000 0000 0001 1111
hash2  1111 1111 1111 1111 0000 1111 0001 0101
&结果   0000 0000 0000 0000 0000 0000 0001 0101 = 21(index = 21的位置)

6.3 扩容总结:

数据扩容 -> 2倍扩容 -> 重新对map中的每一个元素进行寻址->通过判断二进制结果是否多出来了一个bit为,判断index的位置是否变化;

如果数组的长度扩容之后 = 32,重新对每个hash值进行寻址,也就是用每个hash值跟新数组的length - 1进行与操作

  • 判断二级制结果是否多出来一个bit的1
  • 如果没有多,那么还是原来的index
  • 如果多了出来,那么新的index = oldIndex + oldCap
  • 通过这个方法避免了rehash的时候,用每个hash对数据的长度进行取模,取模的性能不高,位运算的性能比较高。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/229082.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CMA、CNAS软件检测公司分享:压力测试应关注的指标和面临的问题

软件压力测试是容易被传统企业忽视的测试点,用户人数一旦超过预期,极易造成软件产品卡顿、崩溃的情况,不利于用户正常使用,严重影响企业公信力和盈利水平。今天卓码软件测评小编来聊聊压力测试过程中应该关注的指标和会面临的问题…

PLC、RS485、变频器通讯接线图详解

plc与变频器两者是一种包含与被包含的关系,PLC与变频器都可以完成一些特定的指令,用来控制电机马达,PLC是一种程序输入执行硬件,变频器则是其中之一。 但是PLC的涵盖范围又比变频器大,还可以用来控制更多的东西&#x…

【ProcessOn】流程图咏道图Axure自定义元件使用----含流程图案例

目录 一,ProcessOn 1.1 ProcessOn是什么 1.2 ProcessOn应用场景 1.3 流程图 1.4 泳道图简介 1.5 Process网址与界面简介 二,流程图案例 2.1 门诊流程图 2.2 住院流程图 2.3 药房药库流程图 2.4 会议OA流程图 三,Axure自定义元件 …

WEB渗透—PHP反序列化(三)

Web渗透—PHP反序列化 课程学习分享(课程非本人制作,仅提供学习分享) 靶场下载地址:GitHub - mcc0624/php_ser_Class: php反序列化靶场课程,基于课程制作的靶场 课程地址:PHP反序列化漏洞学习_哔哩…

嵌入式培训-数据结构-day23-线性表

线性表 线性表是包含若干数据元素的一个线性序列 记为: L(a0, ...... ai-1, ai, ai1 ...... an-1) L为表名,ai (0≤i≤n-1)为数据元素; n为表长,n>0 时,线性表L为非空表,否则为空表。 线性表L可用二元组形式描述…

字符函数字符串函数

islower 是能够判断参数部分的 c 是否是⼩写字⺟的。 练习&#xff1a; 写⼀个代码&#xff0c;将字符串中的⼩写字⺟转⼤写&#xff0c;其他字符不变。 #include <stdio.h> #include <ctype.h> int main () {int i 0;char str[] "Test String.\n"…

diffuser为pipeline设置不用的scheduler

查看默认的schedulers&#xff1a; 使用默认的schedulers生成数据 查看默认scheduler的默认配置&#xff0c;定义了采样器中的相关参数&#xff0c;网上关于DDPM和DDIM的文章较多&#xff0c;可以先去看看这两种schedulers&#xff1a; 修改scheduler&#xff0c;可以用于…

【总结】THUPC2024

队名&#xff1a;消灭智哥 队友&#xff1a;zbh&#xff0c;hrl 比赛前一天组的队。队名源于及其智慧的对面楼的宿管。 复赛就不用想了&#xff0c;就体验一下 ACM 的队伍赛制。 去年一题没切&#xff0c;被队友 szt 单人切 3 带飞。现在 szt 已经是高贵的华附哥了。 今年我…

Linux——进程地址空间与进程控制

进程地址空间与进程控制 文章目录 进程地址空间与进程控制1. 进程地址空间1.1 进程地址空间的引入1.1 进程地址空间的特点1.2 页表1.3 C/C的地址1.4 进程地址空间 页表的优势 2. 进程控制2.1 进程创建2.1.1 写时拷贝 2.2 进程终止2.2.1 进程退出码2.2.2 异常信号码2.2.3 errno…

前端对接 —— 周末

1.点击校验 点击校验 宇哥 记得过滤 不能校验的数据&#xff08;我后端还要检验吗&#xff1f;&#xff09; 2.前端数据对接 这个可以吗&#xff1f; 这种的可以吗&#xff1f;

go原生http开发简易blog(一)项目简介与搭建

文章目录 一、项目简介二、项目搭建前置知识三、首页- - -前端文件与后端结构体定义四、配置文件加载五、构造假数据- - -显示首页内容 代码地址&#xff1a;https://gitee.com/lymgoforIT/goblog 一、项目简介 使用Go原生http开发一个简易的博客系统&#xff0c;包含一下功能…

使用堆排序算法

使用堆排序算法&#xff08;升序&#xff0c;建大堆顶&#xff09;完善此程序。&#xff08;注&#xff1a;截图为堆排序初始化后的大堆顶结果&#xff0c;详见源代码&#xff09; #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #define N 10void input(int a[], …

【react.js + hooks】基于事件机制的跨组件数据共享

跨组件通信和数据共享不是一件容易的事&#xff0c;如果通过 prop 一层层传递&#xff0c;太繁琐&#xff0c;而且仅适用于从上到下的数据传递&#xff1b;建立一个全局的状态 Store&#xff0c;每个数据可能两三个组件间需要使用&#xff0c;其他地方用不着&#xff0c;挂那么…

MySQL日志管理,备份与恢复

备份的主要目的是灾难恢复&#xff0c;备份还可以测试应用、回滚数据修改、查询历史数据、审计等。 而备份、恢复中&#xff0c;日志起到了很重要的作用 MySQL日志管理是数据库管理中的一个重要方面&#xff0c;它可以用于诊断问题、监控性能、进行故障恢复等。MySQL主要有几种…

【合成数字】合成类游戏-uniapp项目开发流程详解

以前玩过2048游戏&#xff0c;从中发现规律&#xff0c;想到跟合成类游戏相似&#xff0c;知道为什么很相似吗&#xff0c;在这里&#xff0c;做一个数字合成游戏玩玩吧&#xff0c;感兴趣的话可以看看&#xff0c;这里给大家讲一讲数字合成游戏的开发过程。 文章目录 创建项目…

Pandas-DataFtame的索引与切片(第3讲)

Pandas-DataFtame的索引与切片(第3讲)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ�…

【动态读取配置文件】ParameterTool读取带环境的配置信息

不同环境Flink配置信息是不同的&#xff0c;为了区分不同环境的配置文件&#xff0c;使用ParameterTool工具读取带有环境的配置文件信息 区分环境的配置文件 三个配置文件&#xff1a; flink.properties&#xff1a;决定那个配置文件生效 flink-dev.properties&#xff1a;测…

深入理解GPIO概念详讲

学习目标 了解mos管的使用了解GPIO输出模式了解GPIO输入模式理解ARM系列GPIO相关理论掌握GD32几种GPIO工作模式编码实现学习内容 基础概念 GPIO,全称为“通用输入/输出”(General Purpose Input/Output),是计算机系统中用于与外部世界进行数字通信的一种接口标准。它允许…

主持知识竞赛类节目的一般流程是什么

竞争性的团队活动&#xff0c;更适合青年的特点&#xff0c;更容易得到青年的支持&#xff0c;也是"离教于乐"的好方式。 这类活动可从内容和特点上分为知识性竞赛&#xff0c;技能性竞赛&#xff0c;文娱性竞赛&#xff0c;体育竞技性竞赛等形式。 知识性竞赛&…

【VMware安装及虚拟机配置】

1. 下载VMware 进入 VMware Workstation 17 Pro下载链接 下拉到如下位置&#xff0c;点击DOWNLOAD 2. 安装VMware 参考&#xff1a;虚拟机VMware下载与安装教程 本次安装是vmware 17&#xff0c;安装步骤差不多&#xff0c;只参考第二部分即可。 3. 激活VMware 密钥&…