Map (三) HashMap 如何利用 hash 计算存储位置

HashMap 的底层实现(判断元素存放的位置,解决哈希冲突,优化扩容) 在Java中,保存数据有两种比较简单的数据结构:数组和链表。数组的特点是:寻址容易,插入和删除困难;链表的特点是:寻址困难,但插入和删除容易;所以我们将数组和链表结合在一起(即散列表),发挥两者各自的优势 阅读详情

我们在看 HashMap 的源码的时候经常能看到 tab[i = (n - 1) & hash]) 这么一串代码。他是专门用来计算当前 key 存储的位置,并获取当前存储位置的元素,进行后续的判断。

让我们用图的形式更直观的看一下它是如何怎么计算的吧。
123
i = 9 即 tab[9]

这就是 HashMap 的精华所在,不论是 get() 还是 put() 都是通过上述的方法计算当前位置是否存在值或获取当前位置的值。这也是 HashMap 为什么数组的长度都为 2^n 的原因,这种操纵字节的计算方法具有足够的高效性。

所以这段代码 p = tab[i = (n - 1) & hash] 可以理解为,将 hash 的 bit 位截取到 (n - 1) 的 bit 位长度。并找到该字节对映的 node 数组坐标中的值。

也间接的证明的 key 的存储位置和 key 的 hash 低位有着紧密的联系(因为通常情况下,我们的 Map 也不会太大)

相比较而言:但是因为和低位关系紧密,所以造成的碰撞的几率会大很多。对于不同的 key ,如果高位不同的多,低位相同的多,碰撞概率相应的也增加了。

而 HashMap 为了解决这方面问题,用了两个位运算方法将计算出来的 hashCode 通过高位的不同也影响到低位变化,使低位的最终结果是通过高位和低位计算得到的。

    static final int hash(Object key) { 
         int h;
        return (key == null) ? 0 :(h = key.hashCode()) ^ (h >>> 16);
    }

^ 的意思就是位运算中,同一位置两个值相同的为 0 ,不同为的 1

这就可以真正的动一位则动全身。不论高位还是低位,只要有一位不同,计算存储位置相同的概率就会大幅度降低(但是还是有的)。


Map (一) HashMap 构造函数的秘密
Map (二) HashMap put()方法详细解刨
Map (三) HashMap 如何利用 hash 计算存储位置
Map (四) HashMap 已故事的角度理解 resize()
Map (五) HashMap get()

一文弄懂HashMap中所有的位运算,理解HashMap设计的精妙! 大家好,我是春风。hashmap经常会被作为我们面试的热身问题。当你讲完自我介绍,面试官上下翻看着你的简历,余光还瞟一眼你的状态和形象。入定,面试官淡淡的说出:请简单讲一下hashmap?或者你理解的hashMap?其实这种泛泛的问法一般是考验面试者的逻辑能力和表述能力,你是否能有条不紊的讲出hashmap的结构,put大致流程等等,回答时除了流程清晰,我们也可以稍微带一点源码上的理解,来体现我们的深度。当然很多情况下,你自己不体现,那面试官会帮你体现~这就是接下来通常会问的hashmap底层原理了,底层原 阅读详情

相关推荐

HashMap如何确定key的存储位置

将传入的参数 key 调用自身的方法 hashCode() 得到哈希值 h。根据哈希值 h 调用扰动函数 hash() 计算 h ^ (h >>> 16) 得到扰动后的哈希值 hash。根据哈希值 hash 取模操作 hash & (n - 1) 从而确定 key 的存储位置。以上就是本篇文章的全部内容了。

weixin_64403990的博客 442

HashMap存储位置计算

HashMap产生hash碰撞一般说法是key的hashCode值一样,其实这种说法是不严谨的,准确说底层计算下标值一样(废话),当然,key的hashCode的值一样是最明显的原因,而hashCode值不同也会导致hash冲突。 HashMap为了存取高效,要尽量较少碰撞,就是要尽量把数据分配均匀,每个链表长度大致相同,这个实现就在把数据存到哪个链表中的算法; 这个算法实际就是取模,hash...

meser88的博客 2897

散列算法、斐波那契散列

需要注意的是,不同的散列算法具有不同的特点和用途,选择哪种算法取决于具体的应用场景和需求。:当HashMap中的元素数量超过其容量(capacity)的负载因子(load factor,默认为0.75)时,HashMap会进行扩容,即创建一个新的、容量更大的数组,并重新计算所有元素的散列值和新位置。综上所述,乘法散列(或更广泛地说,散列算法中的扩容机制)使用2的幂值作为每次的扩容条件,主要是为了提高效率、保证哈希分布的均匀性、优化内存利用率、简化实现以及平衡空间和时间成本。

猪猪 1699

HashMap

一、数据结构 顺序存储: 性质:连续的存储单元来存储数据(逻辑上连续,物理上也连续) 特点:随机存取。适合查找,不适合增删;更节约空间 链式存储: 性质:非连续的存储单元来存储数据(逻辑上连续,物理上不一定连续) 特点:非随机存取。适合增删,不合适查找;有指针域,空间利用率比顺序存储低 索引存储: 性质:通过增加索引(相当于书的目录),来检索目标,一般使用B+树实现 特点:检索快,插入慢。费空间 延伸:B+树和B-树的最主要区别之一是B+树只有叶子节点才存储data信息,而B-树在其他节点也存储

weixin_44495008的博客 1069

Java面试要点56 - Java HashMap源码解析:哈希算法

在使用自定义对象作为HashMap的key时,正确实现hashCode()和equals()方法是至关重要的。这两个方法需要满足一致性要求,即相等的对象必须具有相同的哈希码。// 正确实现hashCode()方法@Override// 使用不变的字段计算哈希码// 正确实现equals()方法@Overrideif (!User user1 = new User("1001", "张三");User user2 = new User("1001", "张三");

程序媛学姐的博客 580

ABB RobotWare数据包全版本归档与高效获取指南

记得去年有个汽车产线升级项目,客户现场用的是RobotWare 6.05.0166版本,而我的RobotStudio里只有最新的7.x系列。RobotWare数据包本质上就是ABB机器人的"操作系统镜像",不同版本的机器人控制器需要匹配特定版本的RobotWare。有个容易忽略的细节:偶数版本号(如6.04、6.06)通常比奇数版本更稳定,因为ABB的内部发布策略是偶数版用于正式产线,奇数版多用于测试新功能。最终实现了零停机升级,这个经验告诉我们:版本切换不是简单的覆盖安装,而是需要系统性的验证流程。

weixin_30764883的博客 278

哈希表、Java中HashMap

哈希算法,是一类算法; 哈希表(Hash Table)是一种数据结构; 哈希函数,是支撑哈希表的一类函数; Map是映射、地图的意思,在Java中Map表示一种把K映射到V的数据类型; HashMap是Java中用哈希数据结构实现的Map; 一、Hash算法 1. 是什么? 查词典 先来看英语翻译: hash 英 [hæʃ] 美 [hæʃ] n. 剁...

「有且仅有」 2万+

无人机中继传输数据链技术,(无人机+自组网)远距离传输技术实现详解

无人机中继传输数据链技术是指利用无人机作为空中移动中继节点,在需要通信的区域上空悬停或移动,以建立和维护通信链路,从而扩展通信范围、提高通信质量和灵活性。1. 通信链路:是无人机中继通信的重要组成部分,包括源节点到中继节点的链路和中继节点到目标节点的链路。同时,它还支持空中到地面的通信,距离大于100km。总的来说,无人机中继传输数据链技术和(无人机+自组网)远距离传输技术都是现代无人机通信领域的重要技术,它们的应用极大地扩展了无人机的通信范围和灵活性,为各种应用场景提供了强有力的支持。

专注多旋翼、复合翼无人机技术研究,从事低空经济行业。 2079

Map<String,Object> map=new HashMap<String,Object>详解

Map是一个接口,即Interface Map<K,V>,其中K-key类型和V-value的类型 它的每个元素包含一个key对象和一个value对象,且在这两个对象之间存在一种映射的对应关系,所有从Map集合中访问元素时,只有指定了key就可以找到对应的value,因此key必须是唯一的且不能重复,当key相同时,后面的value值会覆盖之前的value值。 Map定义的一些通用的方法 Map接口有很多实现类,如TreeMap,Hashtable,SortedMap,HashMa.

wenchang-的博客 5万+

Vivado FFT IP核避坑指南:从Matlab数据生成到FPGA验证的完整流程

本文详细解析了Vivado FFT IP核从Matlab数据生成到FPGA验证的完整流程,重点解决跨平台数据一致性、IP核配置陷阱和验证方法论等核心问题。通过实战案例和避坑指南,帮助工程师高效实现FFT运算的硬件验证,确保结果与Matlab的误差控制在0.3%以内。

weixin_42543046的博客 398

【实战解析】RTL8306MB交换芯片驱动开发中的RMII接口调试陷阱

本文通过一个RTL8306MB交换芯片驱动开发的实战案例,深入剖析了RMII接口调试中的经典陷阱。文章详细描述了因TX_EN与CRS_DV信号线交叉连接错误导致的“静默”故障,并分享了使用逻辑分析仪和示波器进行硬件排查的完整流程与核心技巧,为嵌入式网络驱动开发提供了宝贵的避坑指南。

weixin_29267307的博客 421

Hash函数与算法、哈希查找、哈希冲突解决方法总结

Hash哈希 1.基本概念   Hash,也叫哈希或散列,就是把任意长度的输入(也叫预映射),通过散列算法,变换成固定长度的输出,该输出就是散列值。   若结构中存在和关键字key相等的记录,则必定在H(key)的存储位置上。称该H(key)为哈希函数。   根据设定的哈希函数H(key)和处理冲突方法将一组关键字映射到一个有限的地址区间上,并以关键字在地址区间中的象作为记录在表中的存储位置,这种...

qq_37020594的博客 1万+

源码编译部署篇(二)源码编译milvus成功后如何启动standalone并调试成功!

由于Milvus官方文档只提及如何使用docker安装部署Milvus,关于源码安装方式篇幅较少,因此,我整理撰写了如何通过源码编译方式成功安装Milvus,详见此篇。之所以选择这种复杂的安装方式,可以调试源码进而熟悉Milvus如何搭建整个框架支持AI上层应用功能。根据上篇步骤部署虽然可以成功,然而,我却不能成功启动Milvus服务,这个问题困扰了一两天,现在终于得以解决并能成功调试Milvus源码。接下来,分为三个部分介绍如何启动和成功调试。

qq_43893755的博客 3369

java中HashMap与Hash表详解

转载至https://blog.youkuaiyun.com/u010297957/article/details/51974340 哈希算法,是一类算法; 哈希表(Hash Table)是一种数据结构; 哈希函数,是支撑哈希表的一类函数; Map是映射、地图的意思,在Java中Map表示一种把K映...

风雨落 2万+

ESP32S3接入讯飞在线语音识别教程及配套源代码

本文介绍了如何使用ESP32-S3开发板实现讯飞在线语音识别功能。首先,需要准备硬件设备,包括ESP32-S3开发板、麦克风模块、MicroSD卡模块和扬声器模块。接着,安装Arduino IDE并配置ESP32-S3开发环境,注册讯飞开放平台账号并获取API凭证。然后,通过I2S接口连接麦克风模块,并编写代码实现语音录制、Base64编码、API请求和识别结果处理。代码包括初始化WiFi、麦克风、系统时间,以及录制语音、发送请求、解析响应等功能。最后,通过按键触发录音,并将识别结果输出到串口。

2401_88800025的博客 748

OPPO 数据分析面试题及参考答案

如何设计共享单车数据库的各个字段? 对于共享单车的数据库设计,首先考虑用户相关的字段。用户表可以包含用户 ID,这是一个唯一标识符,用于区分不同用户;姓名,记录用户的真实姓名;联系方式,比如手机号码,方便在出现问题时联系用户;注册时间,记录用户何时开始使用共享单车服务;信用分数,用于衡量用户使用共享单车过程中的行为是否合规,比如是否按时归还车辆等。 车辆信息表要有车辆 ID,这是车辆的唯一标识;车辆类型,例如普通单车、电动单车等;投放时间,即车辆投放到市场的时间;车辆状态,包括是否可用(如正

大模型大数据攻城狮的专栏 1186

js——Set和Map,以及哈希表

1.哈希表 参考链接 哈希表概述: 散列表(Hash table,也叫哈希表),是根据关键值(Key)而直接进行访问的数据结构。也就是说,它通过把关键值key映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数(哈希函数),存放记录的数组叫做散列表。(哈希表一般用数组来存储) 向哈希表中存数据: 根据数据的key值和哈希函数,得到一个数组下标,这个下标的含义是数据在哈希表中的存放的位置。若发生了冲突,则再根据冲突的处理方法来解决冲突。找到最终存放的位置后,将数据存放进去。 在哈希表中查

leilei7407的博客 1万+

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

哈希表(HashMap、HashSet)

是个存储结构:可以让我们一次从表中直接拿到想要的元素,时间复杂度为O(1)为什么能实现O(1):通过哈希(散列)方法,使元素的存储位置和它的关键码之间建立一一映射的关系如果想要存取元素,都是利用哈希(散列)方法 + 关键码,从而计算出index位置,然后进行操作(怎么放的就怎么给它取出来哈希函数示例:此时写着容量是1000,但实际上是2次幂数,容量为1024。

wuweixiaoyue的博客 4145

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

哈希(Hash)算法与查找

哈希算法(Hash)​​,简单来说就是一个“​​数据粉碎机​​”。你给它输入任意内容(文字、文件、密码等),它会吐出一串​​固定长度的乱码​​(叫“哈希值”)。

2302_81240667的博客 2519

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

HashMap中对hash值的计算

1.同一个对象,在hashMap与TreeMap中的哈希值是一样吗?如何保证hash值的稳定性?2.HashMap的链表长度超过8的时候,会将链表转换成红黑树。但是hashCode分布良好的话,链表的长度符合泊松分布,长度达到8的概率小于千万分之一。hashCode是如何保持分布良好的?使用位运算代替传统的取模运算,加快计算效率将hashCode的高位与地位进行搅动运算,进一步减少哈希冲突。

qq_57865884的博客 1231

哈希算法以及哈希表(Hash table,也叫散列表)

hash 英 [hæʃ] 美 [hæʃ] n. 剁碎的食物;混杂,拼凑;重新表述 vt. 搞糟,把…弄乱;切碎;推敲 n. (Hash)人名;(阿拉伯、保、英)哈什;(西)阿什

weixin_59966683的博客 896

深入理解C语言中的哈希算法

深入理解C语言中的哈希算法

深耕嵌入式领用多年, 致力于分享嵌入式领域技术! 1404

解密 Rust HashMap:哈希算法与冲突解决的高效之道

有时我们希望在性能敏感的场景(如游戏引擎或嵌入式系统)中牺牲部分安全性换取速度。Rust 允许通过println!("{:?此时,开发者可替换为更快但安全性较低的算法,如 FNV 或 AHash,以满足特定需求。

rui371的博客 950

Rust 中 HashMap 的哈希算法与冲突解

Rust中的HashMap通过哈希表实现高效键值对存储,默认采用SipHash算法防止哈希碰撞攻击。它使用开放地址法和线性探测处理冲突,当负载因子超过0.75时自动扩容优化性能。在多线程环境中,可使用DashMap替代,其分段锁机制实现线程安全并发访问。合理设置初始容量和负载因子能显著提升HashMap性能,理解其底层原理有助于在不同场景下进行优化。

2501_94033047的博客 807

带你了解!哈希?什么是哈希表?什么是哈希算法?

哈希(Hashing),也被叫做散列,它是一种把任意长度的输入数据(比如一段文本、一个文件等)通过特定的哈希函数转换为固定长度输出(通常是数字或字符串)的过程。不过,由于输入的可能性是无穷的,而输出的范围是有限的,所以难免会出现不同输入产生相同输出的情况,这种情况被叫做哈希冲突。​​作用​​:将任意输入(如字符串、对象)转换为固定范围的整数(图中输出为序列标签2,注意不是下标索引,而且索引+1的映射关系)。​​物理结构​​:一个连续的数组(图中索引范围0-4),每个位置称为​​桶(Bucket)​​。

m0_46808930的博客 3208
上一篇: Map (二) HashMap put()方法详细解刨
下一篇: Map (四) HashMap 已故事的角度理解 resize()
Carey丶zsh
博客等级 码龄10年 15粉丝 47原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值