HashMap的实现原理

hashMap实现原理 1. HashMap概述:   HashMap是基于哈希表的Map接口的非同步实现(Hashtable跟HashMap很像,唯一的区别是Hashtalbe中的方法是线程安全的,也就是同步的)。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。 2. HashMap的数据结构:   在java编程语言中,最基本的结构就是两种,一... 阅读详情
背景

标题中的几个关键字在许多文章都会看到,但是我们并不知道它们是什么意思,下来一起来学习一下。
参考《HashMap实现原理及源码分析》 侵删
参考《Java中HashMap的实现原理》 侵删
参考《谈谈哈希表》 侵删

哈希表

Hash table(也称为散列表、哈希表),当我们需要存储集合或字典,使用线性表、树去存储时,元素在存储结构中的位置与元素的关键码之间不存在直接的对应关系,所以在要搜索一个元素时都需要进行一系列的关键码比较,搜索的效率取决于搜索过程进行的比较次数。而散列表(Hash table)是表示集合和字典的另一种有效方法,它提供了一种完全不同的存储和搜索方式,通过关键码映射到表中某个位置来存储元素,然后根据关键码用同样的方式直接访问。

用自己的话解析

存储数据时,用其他结构都需要对关键码一一比较,搜索效率可能比较低。而哈希表是将关键码和存储位置建立一个映射关系,如存储时,关键字.hashCode()的方法得到一个数组的下标,然后把该Entry(存储对象)存储在该Bucket(桶)里,那么就能大大提高搜索效率。由于hashCode()的计算规则,有可能不同的Entry得到的下标是一样的(哈希冲突),Bucket的结构就设计成单链表,存储时,如果Bucket不为空,则把Entry放进单链表里。在单链表搜索时对比关键码获得Entry。

为什么重写类的equals方法时,也需要重写hashCode方法

正确的状态:当两个不对象相等,即equals方法返回false时,但两对象hashCode方法返回的值相等,那岂不是天下大乱了?
通过hashCode就无法在哈希表中获取到正确的对象。所以一定要保证不相等的对象,返回的hashCode也不一致。另外,两个对象的hashCode()的数值相等,但两个对象用equals方法不一定相等。

equals和==

==用于比较引用和比较基本数据类型时具有不同的功能:
比较基本数据类型,如果两个值相同,则结果为true
而在比较引用时,如果引用指向内存中的同一对象,结果为true;

equals()
作为方法,实现对象的比较。由于==运算符不允许我们进行覆盖,也就是说它限制了我们的表达。因此我们复写equals()方法,达到比较对象内容是否相同的目的。而这些通过==运算符是做不到的。

object类的equals()方法的比较规则为:如果两个对象的类型一致,并且内容一致,则返回true,这些类有:
java.io.file,java.util.Date,java.lang.string,包装类(Integer,Double等)

String s1=new String("abc");
String s2=new String("abc");
System.out.println(s1==s2); //返回false
System.out.println(s1.equals(s2)); //返回true
一些哈希函数的实现方法

直接定址法:这个方法我们在上述例子中有用到过,取关键字的或关键的某一个线性函数值为哈希地址。即:Hash(key)=key或者Hash(key)=a*key+b。这种构造方法下由于地址集合和关键字集合大小一样,所以并不会有冲突的发生。但是这种方法并不常用。
除留余数法:这个方法我们在上述例子中也有用到过,取关键字被某一个不大于哈希表长m的数p除后所余得的数为哈希地址。即Hash(key)=key MOD p,p<=m(m为哈希表长)。这种方法比较简单也很常用。
数字分析法:就是取关键字的若干位数组成哈希地址。当然我们在取的时候要对位数进行分析,尽量减少冲突。
平方取中法:取关键字平方后的中间若干位组成哈希地址。相比于数字分析法优点在于一个数平方之后的中间的几位数和原来的数都有关,因此哈希地址是随机的。

可以看到:在哈希函数构造的时候都是使用的数字,但如果我们的关键字不为数字的时候,我们要先将关键字转化为数字,再用哈希函数得到哈希地址。如上述例子中我们利用学生姓名作为关键字,我们首先要得到学生姓名小写拼音的ASCII码,再用ASCII码作为哈希函数的自变量,从而得到哈希地址。

哈希表处理冲突的方法

之前讲过哈希表的冲突是不可避免的只能减少的,那么如何处理冲突也成了一个不可避免的问题。

什么是处理冲突呢?:由关键字得到的哈希地址上已经有记录存在了,那么“处理冲突”就是要为该关键字的记录找到一个“没有记录存在”的哈希地址。在处理冲突的过程中可能得到一个地址序列Hi(i=1,2,3,4,5,……)。我们在处理哈希冲突的时候可能得到的另一个哈希地址H1也是有记录的,我们要求下一个地址H2,如果H2依然冲突,则找H3,依次类推,直至Hi上没有记录为止。

(1)开放地址法:Hi=(Hash(key)+di)MOD m

其中:Hash(key)为哈希函数,di为增量序列,m为哈希表长。
1、di=1,2,3,4,5……,m-1时称线性探测再散列;
2、di=12,-12,22,-22……….,+k2,-k2(k<=m/2)称之为二次探测再散列。
3、di=伪随机数序列,称之为随机探测在散列。

(2)再哈希法:Hi=RHashi(key) i=0,1,2,3,4….,k. RHashi均是不同的哈希函数,就是说在同义词产生地址冲突的时候用另一个哈希函数去求得另一个哈希地址,一直到不再有冲突

(3)链地址法:链地址法我们在上述例子有用到过。

(4)建立公共溢出区:设哈希函数产生的哈希地址集为[0,m-1],则分配两个表:

一个基本表ElemType base_tbl[m];每个单元只能存放一个元素;

一个溢出表ElemType over_tbl[k];只要关键码对应的哈希地址在基本表上产生冲突,则所有这样的元素一律存入该表中。查找时,对给定值kx 通过哈希函数计算出哈希地址i,先与基本表的base_tbl[i]单元比较,若相等,查找成功;否则,再到溢出表中进行查找。

HashMap的resize

当hashmap中的元素越来越多的时候,碰撞的几率也就越来越高(因为数组的长度是固定的),所以为了提高查询的效率,就要对hashmap的数组进行扩容,数组扩容这个操作也会出现在ArrayList中,所以这是一个通用的操作,很多人对它的性能表示过怀疑,不过想想我们的“均摊”原理,就释然了,而在hashmap数组扩容之后,最消耗性能的点就出现了:原数组中的数据必须重新计算其在新数组中的位置,并放进去,这就是resize。

那么hashmap什么时候进行扩容呢?
当hashmap中的元素个数超过数组大小*loadFactor时,就会进行数组扩容,loadFactor的默认值为0.75,也就是说,默认情况下,数组大小为16,那么当hashmap中元素个数超过16*0.75=12的时候,就把数组的大小扩展为2*16=32,即扩大一倍,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知hashmap中元素的个数,那么预设元素的个数能够有效的提高hashmap的性能。比如说,我们有1000个元素new HashMap(1000), 但是理论上来讲new HashMap(1024)更合适,不过上面annegu已经说过,即使是1000,hashmap也自动会将其设置为1024。 但是new HashMap(1024)还不是更合适的,因为0.75*1000 < 1000, 也就是说为了让0.75 * size > 1000, 我们必须这样new HashMap(2048)才最合适,既考虑了&的问题,也避免了resize的问题。

HashMap与HashSet的底层实现原理 本篇文章将介绍Java中HashMap的底层实现原理,有关HashMap为数组开辟内存的时期,默认的容量,默认负载因子,树化的条件,HashMap的扩容机制,put方法的过程以及HashMap中的哈希函数。 阅读详情

相关推荐

MATLAB/simulink电力系统之变压器仿真+变压器饱和仿真+空载变压器电流畸变原因及仿真+空载合闸励磁涌流仿真+simulink免费仿真资源

单相变压器空载运行时,原边电流主要用来产生主磁场,而电路损耗和铁芯损耗很小,因此即使外加电压很大,空载电流仍然很小。如果想观察某个相对磁导率下电感系数的数值,可以在程序中增加这样的语句,比如,在程序中end语句之后,加上L(100),运行程序后就可以得到相对磁导率为 100时的电感系数值。在交流铁芯线圈中,当交变磁通按照正弦规律变化时,受到磁路饱和的影响,线圈中的电流会发生畸变,并成为尖顶波,这就是所谓的交流磁路电流畸变。需要指出,铁芯内的主磁通Ф可以通过空载时的副边电压从来测量,两者之间的数学关系,即。

m0_37724753的博客 4230

代码随想录——哈希表

代码随想录学习之哈希表

weixin_44602861的博客 207

斯坦福大学CS224d基础1:线性代数知识

本文为斯坦福CS229的内容,也是CS224d课程的背景数学知识。概括了在机器学习和深度学习中用到的大部分线性代数知识。为了便于大家查漏补缺,这里根据英文版本整理了一个中文版本。

龙心尘 2万+

哈希表的基础知识(含代码实现,及使用用例)

哈希表的实现,哈希表的介绍

薛定谔的猫的博客 883

0032期基于深度学习的大米识别-含数据集

083基于深度学习的手势识别小程序版本_含10多种模型包括alexnet、DenseNet、DLA、GoogleNet、Mobilenet、ResNet、ResNeXt、ShuffleNet、VGG、EfficientNet和Swin transformer等10多种模型。117nlp自然语言处理-文本情感分类-joy-sadness-anger-fear-love-surprise。运行02深度学习模型训练.py就会将txt文本中记录的训练集和验证集进行读取训练,训练好后会保存模型在本地。

grehtsfrs的博客 1506

通信算法之249: DJI波形物理层

D-J-I的Lightbridge波形、Ocusync1波形、Ocusync2波形、Ocusync3波形,

leegang12的专栏 1436

谈谈哈希表

一、什么是哈希表?哈希表简单来说可以看作是是对数组的升级,(也有不少人认为哈希表的本质就是数组),那么哈希表和数组的具体联系和区别在哪里呢?我们在利用数组存储数据的时候,记录在数组中的位置是随机的,位置和记录的关键字之间不存在确定的关系。联系:哈希表是由数组实现的。区别:数组中存储的元素的和数组下标没有确定的关系,而哈希表中存储的元素和数组的下标有一个确定的关系,我们将这个确定的关系称之为哈希函数(

刘耀的博客 1352

Oracle EBS GL日记账批“选定以过账”状态数据修复

日记账来源:应收账款。用户操作过账以后,自动提交请求“过账:单一分类账”一直运行中,该请求执行5,6个小时甚至10多个小时无法完成,导致“标准管理器”阻塞大量请求待定,“冲突解决管理器”的待定数量不断增加。系统管理员不得不把该请求强制取消,此时,日记账批的状态处于“选定以过账”(GL_JE_BATCHES.STATUS为S),如下图 检查此日记账批有3千多条日记账题头,由于日记账比较多,日记账的科目余额计算需要大量服务器资源和执行时间比较长。

陈显平的专栏-Oracle EBS 3245

通俗易懂->哈希表详解

什么是哈希表?哈希表,顾名思义,就是一个表。可是为什么叫哈希表?因为这是从老美哪里音译过来的叫做->Hash Table翻译过来就是->哈希表既然是表,那么第一,这个哈希表长什么样子?第二,为什么会有这个哈希表?第三,这个哈希表用来做什么?第三,这个哈希表的特点是什么?第四,什么是取余法?第五,什么是映射?第六,什么是线性探测?第七,什么是哈希桶?一些常见的概念,是什么?要怎么理解?下面一一我来解析。综上,我们来总结一下:1、值很分散,因此哈希表也叫做散列表。

qq_51216031的博客 4万+

手把手教你学simulink(26.7)--控制算法场景示例:基于模型预测控制(MPC)的智能温室环境控制系统

首先,我们需要将温室环境的动力学模型转换为状态空间形式。假设我们有四个状态变量:温度 TT、湿度 HH、光照强度 II 和二氧化碳浓度 CCO2CCO2​,以及四个控制输入:加热器功率 u1u1​、加湿器加湿量 u2u2​、通风扇风速 u3u3​ 和补光灯光照强度 u4u4​。状态空间模型可以表示为:x(t)=[T(t),H(t),I(t),CCO2(t)]Tx(t)=[T(t),H(t),I(t),CCO2​(t)]T 是状态向量。

MHD0815的博客 400

ThingsBoard移动应用详细讲解

ThingsBoard移动应用详细讲解

AldrichEugene 527

Redis底层详解(一) 哈希表和字典

一文读懂哈希表

英雄哪里出来 33万+

ardupilot 获取避障传感器数据

本节主要记录自己学ardupilot的避障代码过程,首先看下怎么注册避障传感器,然后怎么获取避障数据。

陌城烟雨 5524

HashMap底层实现原理解析

一:HashMap底层实现原理解析 我们常见的有数据结构有三种结构:1、数组结构 2、链表结构 3、哈希表结构 下面我们来看看各自的数据结构的特点: 1、数组结构: 存储区间连续、内存占用严重、空间复杂度大 优点:随机读取和修改效率高,原因是数组是连续的(随机访问性强,查找速度快) 缺点:插入和删除数据效率低,因插入数据,这个位置后面的数据在内存中都要往后移动,且大小固定不易动态扩展。 2、链表结构:存储区间离散、占用内存宽松、空间复杂度小 优点:插入删除速度快,内存利用率高,没有固定大小,扩展灵活

qq_43370771的博客 12万+

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

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

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

HashMap底层实现原理详解

本文深入讲解了Java中HashMap的实现原理与特性。首先介绍了HashMap的基本概念和常用方法,包括put、get、remove等操作。然后分析了JDK7和JDK8中HashMap的区别,指出JDK8引入了红黑树优化性能。重点解析了HashMap的扩容机制和容量设计,包括默认负载因子0.75的合理性、扩容规则以及初始容量16的原因。最后比较了不同JDK版本下HashMap的结构变化,JDK7使用数组+链表,而JDK8优化为数组+链表+红黑树的结构,并改变了节点插入顺序。文章通过详细的源码分析和问题解答

Hai的博客 2万+

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

HashMap底层实现原理

HashMap实现原理 1.概述 HashMap是基于哈希表的Map接口的非同步实现。元素以键值对的形式存放,并且允许null键和null值,因为key值唯一(不能重复),因此,null键只有一个。另外,hashmap不保证元素存储的顺序,是一种无序的,和放入的顺序并不相同(此类不保证映射的顺序,特别是它不保证该顺序恒久不变)。HashMap是线程不安全的。 2.继承关系 public class HashMap<K,V> extends AbstractMap<K,V> i

fengxi_tan的博客 2万+

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

HashMap实现原理分析

HashMap其实也是一个线性的数组实现的,所以可以理解为其存储数据的容器就是一个线性数组。这可能让我们很不解,一个线性的数组怎么实现按键值对来存取数据呢?这里HashMap有做一些处理。   首先HashMap里面实现一个静态内部类Entry,其重要的属性有 key , value, next,从属性key,value我们就能很明显的看出来Entry就是HashMap键值对实现的一个基础bean,我们上面说到HashMap的基础就是一个线性数组,这个数组就是Entry[],Map里面的内容都保存在Ent

Alpha's 学习笔记 46万+

HashMap实现原理

检索键值对:当调用get()方法检索键值对时,首先会根据键的哈希值计算出哈希码,然后通过哈希码和数组长度取模计算出在数组中的索引位置。存储键值对:当调用put()方法存储键值对时,首先会根据键的哈希值计算出哈希码,然后再通过哈希码和数组长度取模计算出在数组中的索引位置。扩容后,新的容量为原容量的两倍,并且需要重新计算每个键值对的哈希码和索引位置,将键值对重新存储到新的数组中。的获取操作通过计算键的哈希值,找到对应的桶,然后在桶中遍历链表或红黑树以找到匹配的键。时,会触发扩容操作,默认扩容为原来的 2 倍。

Flying_Fish_roe的博客 1344

HashMap 实现原理

HashMap 通过哈希函数将键映射到数组的索引位置,使用链地址法解决冲突,并在链表长度超过阈值时转换为红黑树以优化性能。当元素数量超过阈值时,会触发扩容操作,数组容量加倍,所有元素重新映射。HashMap 不是线程安全的,多线程环境中应使用 ConcurrentHashMap 或外部加锁。

耐心的L的博客 948

HashMap的实现原理及部分源码分析

HashMap的实现原理及部分源码分析 ​  Java8拥有增强的Map集合,Map是用来保存具有映射关系的数据。Map接口提供了大量的实现类,典型的实现有 HashMap和Hashtable等。Hashtable从它的类名看起来就很古老,因为它的命名都没有遵守Java的命名规范:每个单词首字母都应该大写。 HashMap(哈希表又叫散列表),在数据结构我们已经接触过,它的应用非常广泛,...

weixin_42378758的博客 268

HashMap 的实现原理

HashMap 的实现原理? 可以参考: https://baijiahao.baidu.com/s?id=1589800850701839003&wfr=spider&for=pc https://www.cnblogs.com/chengxiao/p/6059914.html#!comments https://baijiahao.baidu.com/s?id=16...

ConstXiong 8385
上一篇: 单向链表的java实现
下一篇: Android性能优化之布局优化
A_xun_A
博客等级 码龄17年 10粉丝 42原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值