首页 > 其他分享 >HashMap底层实现原理解析

HashMap底层实现原理解析

时间:2023-07-01 10:32:42浏览次数:43  
标签:HashMap equals 数组 链表 哈希 解析 节点 底层

我们常见的有数据结构有三种结构:

数组结构 链表结构 哈希表结构 下面我们来看看各自的数据结构的特点: 1)数组结构: 存储区间连续、内存占用严重、空间复杂度大

优点:随机读取和修改效率高,原因是数组是连续的(随机访问性强,查找速度快) 缺点:插入和删除数据效率低,因插入数据,这个位置后面的数据在内存中都要往后移动,且大小固定不易动态扩展。 2)链表结构:存储区间离散、占用内存宽松、空间复杂度小

优点:插入删除速度快,内存利用率高,没有固定大小,扩展灵活 缺点:不能随机查找,每次都是从第一个开始遍历(查询效率低) 3)哈希表结构:结合数组结构和链表结构的优点,从而实现了查询和修改效率高,插入和删除效率也高的一种数据结构

HashMap底层是哈希表结构

HashMap底层实现原理解析_哈希表

HashMap中 的put()和get()的实现原理:

1、map.put(k,v)实现原理

(1)首先将k,v封装到Node对象当中(节点)。 (2)然后它的底层会调用K的hashCode()方法得出hash值。 (3)通过哈希表函数/哈希算法,将hash值转换成数组的下标,下标位置上如果没有任何元素,就把Node添加到这个位置上。如果说下标对应的位置上有链表。此时,就会拿着k和链表上每个节点的k进行equal。如果所有的equals方法返回都是false,那么这个新的节点将被添加到链表的末尾。如其中有一个equals返回了true,那么这个节点的value将会被覆盖。

2、map.get(k)实现原理

(1)先调用k的hashCode()方法得出哈希值,并通过哈希算法转换成数组的下标。 (2)通过上一步哈希算法转换成数组的下标之后,在通过数组下标快速定位到某个位置上。如果这个位置上什么都没有,则返回null。如果这个位置上有单向链表,那么它就会拿着K和单向链表上的每一个节点的K进行equals,如果所有equals方法都返回false,则get方法返回null。如果其中一个节点的K和参数K进行equals返回true,那么此时该节点的value就是我们要找的value了,get方法最终返回这个要找的value。

为何随机增删、查询效率都很高的原因是?

增删是在链表上完成的,而查询只需扫描部分,则效率高。 HashMap集合的key,会先后调用两个方法,hashCode and equals方法,这这两个方法都需要重写。

为什么放在hashMap集合key部分的元素需要重写equals方法?

因为equals方法默认比较的是两个对象的内存地址

HashMap红黑树原理分析

相比 jdk1.7 的 HashMap 而言,jdk1.8最重要的就是引入了红黑树的设计,红黑树除了插入操作慢其他操作都比链表快,当hash表的单一链表长度超过 8 个的时候,数组长度大于64,链表结构就会转为红黑树结构。当红黑树上的节点数量小于6个,会重新把红黑树变成单向链表数据结构。 为什么要这样设计呢?好处就是避免在最极端的情况下链表变得很长很长,在查询的时候,效率会非常慢。

HashMap底层实现原理解析_哈希表_02

  • 红黑树查询:其访问性能近似于折半查找,时间复杂度 O(logn);
  • 链表查询:这种情况下,需要遍历全部元素才行,时间复杂度 O(n);

简单的说,红黑树是一种近似平衡的二叉查找树,其主要的优点就是“平衡“,即左右子树高度几乎一致,以此来防止树退化为链表,通过这种方式来保障查找的时间复杂度为 log(n)。

HashMap底层实现原理解析_hash冲突_03

关于红黑树的内容,网上给出的内容非常多,主要有以下几个特性: 1、每个节点要么是红色,要么是黑色,但根节点永远是黑色的;

2、每个红色节点的两个子节点一定都是黑色;

3、红色节点不能连续(也即是,红色节点的孩子和父亲都不能是红色);

4、从任一节点到其子树中每个叶子节点的路径都包含相同数量的黑色节点;

5、所有的叶节点都是是黑色的(注意这里说叶子节点其实是上图中的 NIL 节点); 在树的结构发生改变时(插入或者删除操作),往往会破坏上述条件 3 或条件 4,需要通过调整使得查找树重新满足红黑树的条件。

HashMap的原理1.7 和1.8 的区别

1、jdk1.7中底层是由数组+链表实现;jdk1.8中底层是由数组+链表/红黑树实现 2、可以存储null键和null值,线程不安全 3、初始size为16,扩容:newsize = oldsize*2,size一定为2的n次幂 4、扩容针对整个Map,每次扩容时,原来数组中的元素依次重新计算存放位置,并重新插入 5、当Map中元素总数超过Entry数组的75%,触发扩容操作,为了减少链表长度,元素分配更均匀

什么是Hash冲突

当两个key通过hashCod计算相同时(其实hashCode是随机产生的,是有可能hashCode相同),则发生了hash冲突,开放定址法、再哈希法、链地址法、建立公共溢出区

HashMap解决hash冲突的方式

用链表。当发生hash冲突时,则将存放在数组中的Entry设置为新值的next,说白就是比如A和B都hash后都映射到下标i中,之前已经有A了,当map.put(B)时,将B放到下标i中,A则为B的next,所以新值存放在数组中,旧值在新值的链表上

开放定址法:

当关键字key的哈希地址p=H(key)出现冲突时,以p为基础,产生另一个哈希地址p1,如果p1仍然冲突,再以p为基础,产生另一个哈希地址p2,…,直到找出一个不冲突的哈希地址pi ,将相应元素存入其中

再哈希法:

同时构造多个不同的哈希函数,当哈希地址Hi=RH1(key)发生冲突时,再计算Hi=RH2(key)……,直到冲突不再产生。

链地址法:

这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。

建立公共溢出区:

将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表。

标签:HashMap,equals,数组,链表,哈希,解析,节点,底层
From: https://blog.51cto.com/u_16154651/6598287

相关文章

  • 深度理解Iterator底层源码
    publicabstractclassAbstractList<E>extendsAbstractCollection<E>implementsList<E>{//外部操作数:记录添加数据、删除数据的次数(记录元素个数变化的次数) protectedtransientintmodCount=0;//4}这段代码是一个抽象类AbstractList,实现了List接口。下面是对代码......
  • .NET 7 新特性全面解析
    在2021年11月8日发布的.NET6当前已经广泛使用。微软团队已经开始着手为.NET7制定计划和新特性。本文将为您全面解析.NET7的新特性,并提供源代码示例。1.更好的性能.NET7将继续提高运行时性能,改进JIT编译器,减少内存分配,优化GC,以及提高ASP.NETCore和EntityF......
  • String解析及其方法
    String解析及其方法1.前言2.什么是字符串(String)3.字符串(String)的两种创建方式及其区别4.字符串(String)的方法及其部分原码解析5.字符串(String)的弊端1.前言String类代表字符串。Java程序中的所有字符串字面值(如"abc")都作为此类的实例实现。字符串是常量;它们的值......
  • 万字长文解析最常见的数据库恢复算法: ARIES
    万字长文解析最常见的数据库恢复算法:ARIES首发地址:https://mp.weixin.qq.com/s/Kc13g8OHK1h_f7eMlnl4AwIntroduction上图中为基于WAL的数据库的一种可能的架构情况。其中,In-MemoryData为数据库数据在内存中的组织形式,可以是B树,也可以是hashtable或者其他可能的......
  • 【源码分析】Mybatis 的配置解析过程
    博主介绍:✌博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家✌Java知识图谱点击链接:体系化学习Java(Java面试专题)......
  • vue:<img>动态绑定的路径无法解析问题
    问题我们引用图片,正常的静态img图片是这么引用的<imgsrc="@/assets/img/icoms/people.png"/>没问题,只要路径正确在vue中动态绑定路径:src<img:src="@/assets/img/icoms/people.png"/>发现图片根本加载不出来,因为:src根本不能解析@/assets/img/icoms/people.png解决......
  • Hadoop常见问题解析
    Hadoop常见问题解析Hadoop特性1.高可靠性:采用冗余数据存贮方式,即使一个副本发生故障,其他副本也可以保证对外工作的正常进行。2.高效性:作为并行分布式计算平台,hadoop采用分布式存贮和分布式处理两大核心技术,能够高效的处理PB级别的数据3.高可扩展性:hadoop的设计目标是可以高效......
  • Java解析json数据(fastjson2)
    Json数据JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。它以易于阅读和编写的方式来表示结构化数据,常用于在不同系统之间进行数据交互和传输。JSON使用键值对的方式来组织数据,具有以下几个特点:具有简洁的语法:JSON使用了人类可读的文本格式,易于理解和编写。支持......
  • 使用 JCommander 解析命令行参数
    前言如果你想构建一个支持命令行参数的程序,那么jcommander非常适合你,jcommander是一个只有几十kb的Java命令行参数解析工具,可以通过注解的方式快速实现命令行参数解析。这篇教程会通过介绍jcommadner,快速的创建一个命令行程序,最后支持的命令参数功能如下图。这个命......
  • 你没见过的分库分表原理解析和解决方案(二)
    你没见过的分库分表原理解析和解决方案(二)高并发三驾马车:分库分表、MQ、缓存。今天给大家带来的就是分库分表的干货解决方案,哪怕你不用我的框架也可以从中听到不一样的结局方案和实现。一款支持自动分表分库的orm框架easy-query帮助您解脱跨库带来的复杂业务代码,并且提供多......