• 源码硬讲HashMap结构及数据结构转换过程(图+文)


    1 缘起

    补充树相关的知识过程中,学习到红黑树,并查了一些红黑树的应用,
    发现Java提供的数据工具包:HashMap中使用了红黑树,
    之前在应对知识考核时也看了HashMap的相关数据组成,
    但是,没有详细分析数据之间是如何转换存储结构的,
    现在,正好借着学习树以及应用的机会,根据HashMap源码
    详细研究了HashMap的数据转换过程,
    分享如下,
    帮助读者轻松应对知识考核与交流。

    2 分析

    2.1 理论:回顾HashMap

    HashMap是一个组合的数据结构
    根据自己动手丰衣足食的设计原则,当某种开发语言不支持更加高效的数据结构存储数据时,
    开发者可根据实际需要,编写自己的数据结构,
    这不,Java工具包开发者组合了数组、链表和红黑树,创造了HashMap,
    集相对高效的CURD于一身。
    老规矩,根据理论,
    先看看HashMap的数据结构,如下图所示,
    由图可知,HashMap默认的数组元素有16个,
    数组中的元素存储情况:
    (1)key没有Hash冲突,则按照kv形式存储,如key2对应的形式;
    (2)key有Hash冲突且冲突的key个数小于7个,使用链表存储,如key1对应的形式;
    (3)key有Hash冲突且冲突的key个数大于等于7个,使用红黑树存储,如key3对应的形式。

    在这里插入图片描述

    2.2 实践:新增数据

    使用HashMap存储数据,暴露给用户的方法为put,源码如下图所示,
    由源码可知,put方法中,调用了putVal方法,这个方法才是实际的存储数据和数据结构转换的方法。
    位置:java.util.HashMap#put
    在这里插入图片描述

    既然putVal才是最终的奥义,
    那么继续看看这个方法的真实面目,如下图所示,
    新增数据,
    我已经将数据的类型和数据结构的变化在图中标出,
    各位习者耐心看下,设计非常巧妙,
    Node<>[]即数组;
    p.next即链表,
    treeifyBin即红黑树。

    位置:java.util.HashMap#putVal
    在这里插入图片描述

    2.3 Node

    HashMap的Node有两种功能,
    (1)直接存储kv;
    (2)转换为单向链表
    源码如下图所示,有源码可知,属性key、value即可直接存储kv;
    属性next即单向链表结构,使用链表存储数据。
    在这里插入图片描述

    2.4 TreeNode

    前面的Node用于存储kv或者单向链表,
    那么,红黑树则使用TreeNode存储数据,
    属性,parent连接父节点,left和right是该节点的左右节点,prev前驱节点,删除时断开与next的连接,
    red用于标识当前节点的特性:红或黑。
    位置:java.util.HashMap.TreeNode
    在这里插入图片描述

    2.5 树化:构建红黑树

    树化的方法为treeifyBin,即构建树化容器,
    源码如下图所示,
    有源码可知,首先构建TreeNode,然后通过treeify构建红黑树,
    是的,核心是treeify方法。
    位置:java.util.HashMap#treeifyBin
    在这里插入图片描述
    构建红黑树:
    源码如下图所示。
    位置:java.util.HashMap.TreeNode#treeify
    在这里插入图片描述

    3 小结

    (1)HashMap由3种数据结构构成:数组、单向链表和红黑树;
    (2)数据结构转换过程:
    (2.1)key没有Hash冲突,则按照kv形式存储,如key2对应的形式;
    (2.2)key有Hash冲突且冲突的key个数小于7个,使用链表存储,如key1对应的形式;
    (2.3)key有Hash冲突且冲突的key个数大于等于7个,使用红黑树存储,如key3对应的形式。
    (3)红黑树转换时,先构建TreeNode数组,然后转换为红黑树,红黑树转换的核心方法为:java.util.HashMap.TreeNode#treeify。

  • 相关阅读:
    灌装机的灌装结构设计及仿真(lunwen+任务书+开题+文综+翻译及原文+答辩PPT+cad图纸+UG模型及运动仿真)
    【在线教育】EasyExcel入门
    大型语言模型的推理演算
    XGBoost原生接口和Sklearn接口参数详解
    《最新出炉》系列初窥篇-Python+Playwright自动化测试-34-处理https 安全问题或者非信任站点-下篇
    理解 Vue3 里的 defineProps 和 defineEmits
    Java Future学习
    java中stringbuffer用法:StringBuffer实现高效字符串拼接
    Windows10安装Docker(基于WSL2,包含WSL2安装教程)
    css多个物体椭圆旋转
  • 原文地址:https://blog.csdn.net/Xin_101/article/details/126947020