HashMap详解(扩容机制、底层结构、适用场景)

 1、特点

  • 底层是链表+数组,JDK1.8开始,当链表长度超过8时,会将链表转换为红黑树。

  • 储存的是key-value类型数据。

  • key值不允许重复,key重复会被覆盖,value允许重复。

  • 数据储存无序(不记录存入的顺序)。

  • key和value都允许为空,但是只能有一个空的key。

2、相较于其他集合

  • HashMap是一种基于哈希表的Map接口实现。它提供了常数时间的getput操作,这意味着无论HashMap中有多少元素,获取和插入元素所需的时间都大致相同。这是因为HashMap使用了哈希表来存储键值对,它通过计算键的哈希值来快速定位键值对在哈希表中的位置。

  • 相比之下,其他一些集合(如ArrayList或LinkedList)需要线性时间来搜索元素,这意味着它们在元素数量增加时性能会下降。

  • 当然,HashMap也有一些局限性。例如,它不保证元素的顺序,而且在某些情况下可能需要进行扩容,这会导致性能下降。

  • HashMap适用于需要快速查找、插入和删除键值对的场景。例如,您可以使用HashMap来存储一个字典,其中键是单词,值是定义。这样,您就可以快速查找单词的定义,而不需要遍历整个字典。

  • 此外,HashMap还可以用于缓存数据,以便快速访问。例如,您可以使用HashMap来存储从数据库中检索的数据,这样下次需要相同数据时,就可以直接从HashMap中获取,而不需要再次查询数据库。

  • 当然,HashMap并不适用于所有场景。例如,如果您需要按照元素插入的顺序来遍历元素,那么您应该使用LinkedHashMap而不是HashMap。如果您需要对元素进行排序,那么您应该使用TreeMap而不是HashMap。

3、底层结构

1.7:数组+链表 (由于是链表长度长了。查询效率不高。所以在设计初衷1.7的hash算法更复杂。数据也更散列)

1.8:数组+链表+红黑树(JDK8中即使用了单向链表,也使用了双向链表,双向链表主要是为了红黑树相关链表操作方便,应该在插入,扩容,链表转红黑树,红黑树转链表的过程中都要操作链表)

Node是链表的节点,它包含了key、value和next三个属性。

TreeNode是红黑树的节点,它包含了key、value、next、left、right和parent六个属性。

 3.1 链表——》红黑树

当链表中的元素个数大于8(此时 node 有9个),并且数组的长度大于等于64时才会将链表转为红黑树。而当红黑树中的元素个数小于等于6时,会将红黑树转为链表形式

    为什么要将链表转化为红黑树呢

链表转换为红黑树的最终目的,是为了解决在map中元素过多,hash冲突较大,而导致的读写效率降低的问题。

    转化的流程

并不是简单地将链表转换为红黑树,而是先判断table的长度是否大于64,如果小于64,就通过扩容的方式来解决,避免红黑树结构化(转化为红黑树浪费性能)。

链表长度大于8有两种情况:

  • table长度足够,hash冲突过多

  • hash没有冲突,但是在计算table下标的时候,由于table长度太小,导致很多hash不一致的
    第二种情况是可以不转为红黑树、改为调用resize方法进行扩容来避免的,扩容后链表长度变短,读写效率自然提高。另外,扩容相对于转换为红黑树的好处在于可以保证数据结构更简单。
    由此可见并不是链表长度超过8就一定会转换成红黑树,而是先尝试扩容

  3.2 红黑树——》链表

在扩容方法 resize()中的“将原Node数组中的元素拷贝到新的Node数组”中的步骤中,如果遍历到的Node元素是一个红黑树的时候,出现了一个split()方法,

该split方法的目的是:将该红黑树进行拆分,然后迁移到新的Node数组中。

(如果拆分后的子树过小(子树的节点小于等于6个),则取消树化,即将其转为链表结构);

介绍一下resize()方法

4、常用方法

  • .put(K key, V value) 将键(key)/值(value)映射存放到Map集合中(也就是将两值存入集合中)

  • .get(Object key) 返回指定键所映射的值,没有该key对应的值则返回 null,即获取key对应的value。(只返回的了value值)

  • . size() 返回Map集合中数据数量,准确说是返回key-value的组数。

  • .clear() 清空Map集合

  • .isEmpty () 判断Map集合中是否有数据,如果没有则返回true,否则返回false

  • .remove(Object key) 删除Map集合中键为key的数据并返回其所对应value值。

  • .containsKey(Object key) 判断是否含有key,如果有返回true,如果没有返回false。

  • .containsValue(Object value) 判断是否含有value。如果有返回true,如果没有返回false。

  • .replace(Object key,Object value)将这个key的value值替换掉,替换为方法为中这个value值。

  • .putAll(HashMap )添加另一个同一类型的map下的所有数据.( 下面为此方法代码)

5、putVal()方法详解

调用HashMap的put方法时,它会调用putVal方法来插入键值对。在putVal方法中,它会进行判断,如果是第一次插入数据,或者达到了扩容阈值会调用resize()方法,对数组进行操作。

在这个方法中会通过数组的长度和键的hash计算出应存入到数组中的下标。index=(length-1)&hash

总之就是将这个键值对节点放入到它应该处于的集合当中的位置。

6、HashMap的扩容

   6.1为什么要进行扩容

我们知道理论上哈希表的读时间复杂度是O(1),但是没有一种哈希方法能保证绝对的哈希均匀,为了解决哈希冲突又往往采用链地址法解决,那这样时间复杂度愈发偏离O(1)了,此时进行扩容,其实是让哈希表分散的更均匀,解决性能不够好的问题。

   6.2如何扩容

HashMap的扩容是通过调用resize()方法实现的。

java1.8+在扩容时,不需要重新计算元素的hash进行元素迁移。

而是用原先位置key的hash值与旧数组的长度(oldCap)进行"与"操作。

  • 如果结果是0,那么当前元素的桶位置不变。

  • 如果结果为1,那么桶的位置就是原位置+原数组 长度

值得注意的是:为了防止java1.7之前元素迁移头插法在多线程是会造成死循环,java1.8+后使用尾插法

注意:

java1.8 扩容的时候会判断当前的桶的位置有没有链表或者红黑树,如果没有链表或者红黑树,那么当前元素还是和JDK1.7中的求法一样,求新的桶的位置。如果有链表,那么链表的元素会按照上述方法求新的桶的位置。如果是红黑树,则会调用split()方法,将红黑树切分为两个链表,之后进行扩容操作。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

html学习

1.框架标签 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><body ><p align"center"><a href "http://www.baidu.com" target"aa">百度&l…

操作指南 | 如何使用API3请求链下数据

API3是一种去中心化解决方案&#xff0c;用于向智能合约平台提供传统且可扩展的API服务&#xff0c;使开发者能够访问如喂价和QRNG等链下资源。 API3由DAO管理&#xff0c;致力于在智能合约功能中轻松访问各种有用数据。 构建者在Moonbeam上可以访问不同的API3服务&#xff1…

机器学习(1)机器学习类型和机器学习的主要概念

0.前提 深度学习&#xff08;Deep Learing&#xff09;是机器学习&#xff08;Machine Learning&#xff09;领域中的一个新的研究方向&#xff0c;在如今的时代研究深度学习的大模型是十分热门的。我不知道有多少人有关注到最近openai的事件啊&#xff0c;说个比较让我惊讶的…

注意力机制(Q,K,V)基本概念

文章目录 一、注意力提示1.1概念1.2生活中的注意力提示1.3注意力机制基本框架小结 二、注意力汇聚2.1概念2.2非参注意力汇聚2.2.1平均汇聚2.2.2Nadaraya-Waston核回归 2.3通用注意力汇聚公式2.4带参数注意力汇聚小结 三、注意力评分函数3.1概念3.2例子 四、遮蔽softmax三四小结…

【数字化转型方法论读书笔记】-数据中台落地实施之法

让数据中台真正落地是实现数字化转型的重中之重。企业做好数据治理、体系建设及人才配备等前期工作后&#xff0c;接下来要做的是数据中台实施落地的关键。 企业首先要掌握数据中台建设的三大核心要素&#xff1a;选对数据建设方式、厘清建设思路、避开数据中台建设误区&#…

桐庐县数据资源管理局领导一行莅临美创科技并带来感谢信

11月23日&#xff0c;浙江桐庐县数据资源管理局党组成员、副局长朱勃一行到访美创科技总部参观交流&#xff0c;并带来感谢信&#xff0c;对美创圆满完成护航亚运政务外网数据网站安全保障工作表示充分肯定。美创科技联合创始人、副总裁胡江涛等进行热情接待并开展交流座谈。 图…

LeetCode Hot100 437.路径总和III

题目&#xff1a; 给定一个二叉树的根节点 root &#xff0c;和一个整数 targetSum &#xff0c;求该二叉树里节点值之和等于 targetSum 的 路径 的数目。 路径 不需要从根节点开始&#xff0c;也不需要在叶子节点结束&#xff0c;但是路径方向必须是向下的&#xff08;只能从…

skywalking 简单操作文档

1.1. 基础概念 1.1.1. 概述 SkyWalking是 apache基金会下面的一个开源 APM项目&#xff0c;为微服务架构和云原生架构系统设计。它通过探针自动收集所需的指标&#xff0c;并进行分布式追踪。通过这些调用链路以及指标&#xff0c;Skywalking APM会感知应用间关系和服务间关系…

LeetCode(34)有效的数独【矩阵】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 36. 有效的数独 1.题目 请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 &#xff0c;验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗…

宏工科技通过CMMI三级认证,软件研发能力获国际权威认可

近日&#xff0c;宏工科技子公司湖南宏工软件成功通过CMMI三级认证并正式获得资质证书&#xff0c;斩获全球软件领域最权威的认证之一&#xff0c;标志着宏工科技在软件技术开发、研发管理、项目管理等多方面获得国际权威认证。 CMMI全称是Capability Maturity Model Integrati…

芯片技术探索:了解构芯片的设计与制造之旅

芯片技术探索:了解构芯片的设计与制造之旅 一、引言 随着现代科技的飞速发展,芯片作为信息技术的核心,已经渗透到我们生活的方方面面。从智能手机、电视、汽车到医疗设备和工业控制系统,芯片在各个领域都发挥着至关重要的作用。然而,对于大多数人来说,芯片仍然是一个神秘…

【23真题】罕见211!数一配英二!

今天分享的是23年合肥工业大学833的信号与系统数字信号处理试题及解析。合工大833考数一英二&#xff0c;这样的搭配还是很少见的。 本套试卷难度分析&#xff1a;22年合肥工业大学833考研真题&#xff0c;我也发布过&#xff0c;若有需要&#xff0c;戳这里自取!平均分为80和…

3D ACIS Modeler和HOOPS Visualize助力鲁班软件打造BIM数字化平台

鲁班软件成立于2001年&#xff0c;始终致力于BIM技术研发和推广&#xff0c;为建筑产业相关企业提供基于BIM技术的数字解决方案&#xff0c;专注打造能够支撑建筑企业集团发展的BIM数字化平台鲁班工程管理数字平台(Luban Builder)&#xff0c;以及可承载园区级或城市级的BIM、C…

NX二次开发UF_CURVE_create_arc_point_center 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CURVE_create_arc_point_center Defined in: uf_curve.h int UF_CURVE_create_arc_point_center(tag_t point, tag_t center, UF_CURVE_limit_p_t limit_p [ 2 ] , tag_t support…

IDEA插件:Apipost-Helper-2.0

我们在编写完接口代码后需要进行接口调试等操作&#xff0c;一般需要打开额外的调试工具。今天就给大家介绍一款IDEA插件&#xff1a;Apipost-Helper-2.0。用它&#xff0c;代码写完直接编辑器内调试、还支持生成接口文档、接口树等功能&#xff0c;并且完全免费&#xff01;非…

3D模型材质编辑器

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 材质贴图&#xff08;Texture Mapping&#xff09;&#xff1a;是在物体着色方面最引人注目、…

对称加密与非对称加密的区别是什么?

对称加密与非对称加密的区别是什么&#xff1f; 对称加密概念&#xff1a;好处和坏处&#xff1a;基本原理 非对称加密概念&#xff1a;工作原理&#xff1a; 两者区别安全性处理速度密钥管理通信双方数量 对称加密 概念&#xff1a; 同一个密钥可以同时用来对信息进行加密和…

如何在vs2017及以前版本(vs2010、vs2015)上添加 添加类型库中的MFC类

有时候当我们新建MFC工程需要使用到微软的一些自带控件&#xff0c;如播放视频要用到Windows media player控件&#xff0c;这时&#xff0c;我们可以通过添加“ActiveX控件中的mfc类(A)”这一选项. 还有有时候我们需要用到“类型库中的MFC类(T)及“MFC ODBC使用者(O)”。那我们…

血的教训------入侵redis之利用python来破解redis密码

血的教训------入侵redis之利用python来破解redis密码 利用强大的python来进行redis的密码破解&#xff0c;过程不亦乐乎&#xff0c;当然也可以用shell脚本 本篇文章只供学习交流&#xff0c;请勿他用&#xff0c;谢谢。 其他相关联的文章 [1]VMware安装部署kail镜像服务器【…

Linux操作系统使用及C高级编程-D15D16内存管理和动态内存使用

内存分区 使用size查看内存使用 动态内存使用 不能返回局部变量的引用&#xff0c;局部变量存放在栈区&#xff0c;空间随着函数结束自动释放 动态申请内存 内存泄漏和内存溢出