首页 > 其他分享 >HashMap底层原理

HashMap底层原理

时间:2023-07-02 13:04:58浏览次数:43  
标签:hash HashMap 数组 链表 哈希 原理 节点 底层

一、HashMap底层实现原理解析

我们常见的有数据结构有三种结构:数组结构; 链表结构; 哈希表结构。

下面我们来看看各自的数据结构的特点:

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底层原理_数组_03

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

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

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

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

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

三、HashMap的原理1.7 和1.8 的区别 jdk1.7中底层是由数组+链表实现;jdk1.8中底层是由数组+链表/红黑树实现 可以存储null键和null值,线程不安全 初始size为16,扩容:newsize = oldsize*2,size一定为2的n次幂 扩容针对整个Map,每次扩容时,原来数组中的元素依次重新计算存放位置,并重新插入 当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个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。 建立公共溢出区:将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表。

标签:hash,HashMap,数组,链表,哈希,原理,节点,底层
From: https://blog.51cto.com/u_16119510/6604462

相关文章

  • 微信读书:从Paxos到Zookeeper:分布式一致性原理与实践(阅读摘录)
    微信读书:从Paxos到Zookeeper:分布式一致性原理与实践(阅读摘录)阅读地址CAP理论CAP理论告诉我们,一个分布式系统不可能同时满足一致性(C:Consistency)、可用性(A:Availability)和分区容错性(P:Partitiontolerance)这三个基本需求,最多只能同时满足其中的两项。BASE理论BASE是Basica......
  • 详解Java中跳跃表的原理和实现
    原文链接及讲解:详解Java中跳跃表的原理和实现java跳表实现importjava.util.Collections;importjava.util.List;importjava.util.stream.Collectors;importjava.util.stream.Stream;/***java跳表实现**@authorlyn*@date2023/6/3018:50*/publicclass......
  • 常见的网络攻击原理及解决方案
    常见的网络攻击原理及解决方案常见的网纲攻击原理及解决方案网络安全是当今互联网时代不可忽视的话题,随着网络技术的发展,网络攻击也日益猖獗和复杂。网络攻击可能会给网站、应用、服务器、数据库等造成严重的损害,甚至导致数据泄露、资金损失、信誉受损等后果。因此,了解常见的网......
  • 从mysql主从复制原理分析故障及延时场景!
    在很多的情况下生产环境所发生的问题,实际上都可以通过其工作原理来解决例如:mysql主从复制原理:  1.当用户在主库中写入数据时,将sql语句的执行写入binlog二进制文件中2.从库会生成一个i/o线程用来监听binlog日志文件的变化,若binlog文件发生变化,那么i/o线程将会提取binlog日志......
  • Node.js 模块化机制原理探究
    前言Node应用是由模块组成的,Node遵循了CommonJS的模块规范,来隔离每个模块的作用域,使每个模块在它自身的命名空间中执行。CommonJS规范的主要内容:模块必须通过module.exports导出对外的变量或接口,通过require()来导入其他模块的输出到当前模块作用域中。CommonJS模块的特......
  • Vue双向数据绑定原理(面试必问) vue双向绑定面试怎么说
    vue.js是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图。具体步骤1、需要observer的数据对象进行递归遍历,包括子属性对象的属性,都加上setter和getter这样的话,给这......
  • 解密Prompt系列10. 思维链COT原理探究
    前一章思维链基础和进阶玩法我们介绍了如何写Chain-of-thoughtPrompt来激活生成逐步推理,并提高模型解决复杂问题的能力,这一章我们追本溯源,讨论下COT的哪些元素是提升模型表现的核心?要进行因果分析,需要把思维链中的不同元素拆解开来,然后通过控制变量实验,来研究不同元素对COT效果......
  • HashMap底层实现原理解析
    我们常见的有数据结构有三种结构: 数组结构 链表结构 哈希表结构下面我们来看看各自的数据结构的特点:1)数组结构:存储区间连续、内存占用严重、空间复杂度大优点:随机读取和修改效率高,原因是数组是连续的(随机访问性强,查找速度快)缺点:插入和删除数据效率低,因插入数据,这个位置后......
  • 深度理解Iterator底层源码
    publicabstractclassAbstractList<E>extendsAbstractCollection<E>implementsList<E>{//外部操作数:记录添加数据、删除数据的次数(记录元素个数变化的次数) protectedtransientintmodCount=0;//4}这段代码是一个抽象类AbstractList,实现了List接口。下面是对代码......
  • NIO效率高的原理之零拷贝与直接内存映射
    零拷贝零拷贝是指避免在用户态(User-space)与内核态(Kernel-space)之间来回拷贝数据的技术。传统IO传统IO读取数据并通过网络发送的流程,如下图   传统IOread()调用导致上下文从用户态切换到内核态。内核通过sys_read()(或等价的方法)从文件读取......