当前位置: 首页 > news >正文

#### go map 底层结构 ####

转自 图解golang map 底层实现 - 掘金

仅做个人备份

目录

#### 整体结构 ####

整体结构的剖析——主要结构:hmap、bucket

key的定位

扩容

#### 整体结构 ####

整体结构的剖析——主要结构:hmap、bucket

(1)hmap

其中标红的【buckets数组(即bmap)】字段为主要字段。

(2)bucket

主要有俩字段:

(1)红色的字节数组,存储map中的key和value,详细结构如下:

并不是key0/value0/key1/value1的形式,这样做的好处是在key和value的长度不同的时候,可以消除padding带来的空间浪费。

(2)蓝色的扩容指针,指向扩容后的bucket的指针,使得bucket会形成一个链表结构,例如下图:

所以,hmapbucket的关系是这样的:

所以,整体的结构应该是这样的:

key的定位

根据key算出hash值,然后hash值的低位用于寻找当前key属于hmap中的哪个bucket,而hash值的高位用于寻找bucket中的哪个key。

扩容

当Go的map长度增长到大于加载因子所需的map长度时,Go语言就会将产生一个新的bucket数组,然后把旧的bucket数组移到一个属性字段oldbucket中。注意并不是立刻把旧的数组中的元素转义到新的bucket当中,而是只有当访问到具体的某个bucket的时候,会把bucket中的数据转移到新的bucket中。

【加载因子】

加载因子是一个阈值,表示散列包含的元素数 除以 位置总数。是一种“产生冲突机会”和“空间使用”的平衡与折中。

加载因子越小,说明空间空置率高,空间使用率小,但是加载因子越大,说明空间利用率上去了,但是“产生冲突机会”高了。

每种哈希表的都会有一个加载因子,数值超过加载因子就会为哈希表扩容。 Golang的map加载因子的公式是:map长度 / 2^B阈值是6.5。其中B可以理解为已扩容的次数。

如下图所示,当扩容的时候,Go的map结构体中,会保存旧的数据,和新生成的数组。

上面部分代表旧的有数据的bucket,下面部分代表新生成的新的bucket。蓝色代表存有数据的bucket,橘黄色代表空的bucket。 扩容时map并不会立即把新数据做迁移,而是当访问原来旧bucket的数据的时候,才把旧数据做迁移,如下图:

注意:这里并不会直接删除旧的bucket,而是把原来的引用去掉,利用GC清除内存。

相关文章:

  • Spring 框架:过滤器 vs 调度器 Servlet vs 拦截器 vs 控制器
  • Java项目源码SSM校园网报修系统
  • NET面试--C#基础
  • 浙大MPA网上报名关键信息点提醒,选错一个,回头重来
  • 消除笔去水印怎么做?教你怎么用这些消除笔软件
  • JAVAFile类以及怎么在目录不存在的情况下创建文件
  • 解决SQL映射文件的警告提示
  • 对比base64图片使用base256加密解密前后的区别
  • python面经(滴滴、理想、momenta)
  • 2022年五一杯数学建模B题矿石加工质量控制问题解题全过程及论文和程序
  • 向移动端发展会是Web3的突破契机吗?
  • 网课答案公众号怎样可以快速调用查题功能
  • 03-JVM-对象内存、执行引擎
  • 本地缓存组件
  • 掌握这25个单行代码技巧,你也能写出『高端』Python代码
  • 【技术性】Search知识
  • 【面试系列】之二:关于js原型
  • AHK 中 = 和 == 等比较运算符的用法
  • codis proxy处理流程
  • Docker: 容器互访的三种方式
  • IP路由与转发
  • java第三方包学习之lombok
  • JDK 6和JDK 7中的substring()方法
  • Linux CTF 逆向入门
  • mac修复ab及siege安装
  • MySQL用户中的%到底包不包括localhost?
  • SAP云平台里Global Account和Sub Account的关系
  • webpack入门学习手记(二)
  • 编写高质量JavaScript代码之并发
  • 猴子数据域名防封接口降低小说被封的风险
  • 讲清楚之javascript作用域
  • 排序算法之--选择排序
  • 前嗅ForeSpider中数据浏览界面介绍
  • 首页查询功能的一次实现过程
  • 新手搭建网站的主要流程
  • 浅谈sql中的in与not in,exists与not exists的区别
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • ​业务双活的数据切换思路设计(下)
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • #Linux杂记--将Python3的源码编译为.so文件方法与Linux环境下的交叉编译方法
  • #LLM入门|Prompt#3.3_存储_Memory
  • (4)Elastix图像配准:3D图像
  • (js)循环条件满足时终止循环
  • (附源码)ssm码农论坛 毕业设计 231126
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (转)AS3正则:元子符,元序列,标志,数量表达符
  • (转)JAVA中的堆栈
  • (转)程序员疫苗:代码注入
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • .Net CF下精确的计时器
  • .net CHARTING图表控件下载地址
  • .NET CORE使用Redis分布式锁续命(续期)问题
  • .net 调用php,php 调用.net com组件 --
  • .NET 中选择合适的文件打开模式(CreateNew, Create, Open, OpenOrCreate, Truncate, Append)
  • .Net开发笔记(二十)创建一个需要授权的第三方组件