Golang Map原理(底层结构、查找/新增/删除、扩缩容)
参考:
- 解剖Go语言map底层实现
- Go语言核心手册-3.字典
一、Go Map底层结构:
Go map的底层实现是一个哈希表(数组 + 链表),使用拉链法消除哈希冲突,因此实现map的过程实际上就是实现哈希表的过程。
先来看下go map底层的具体结构:
type hmap struct {count int // 元素个数,调用len(map)返回这个值B uint8 // bucket数量是2^B, 最多可以放 loadFactor * 2^B 个元素,再多就要扩容了hash0 uint32 // hash seedbuckets unsafe.Pointer // 指向bucket数组的指针(存储key val);大小:2^B oldbuckets unsafe.Pointer // 扩容时,buckets 长度是 oldbuckets 的两倍// ...
}
type bmap struct {topbits [8]uint8 // 高位哈希值数组keys [8]keytype // 存储key的数组values [8]valuetype // 存储val的数组overflow uintptr // 指向当前bucket的溢出桶// 为缓解当存在多个key计算后的哈希值低8位相同的个数大于一个bucket所能存放的数目8个时,且这个map还没达到扩容条件时,做的一种存储设计。
}
在这个哈希表中,主要涉及到的结构体有两个:一个是 hmap
(a header for a go map),一个是 bmap
(a bucket for a go map):
- 对于
hmap
,我们只需要关注其中的buckets
,它是一个指向bmap
结构体类型数组的指针。- 而对于其中的
bmap
:- 高位哈希值
topbits
:数组记录的是当前bucket中key相关的 “索引” - 指向扩容bucket的指针
overflow
:每个 bmap类型的 bucket 最多只能放 8个k-v键值对。如果碰巧有key的哈希值一样的新数据存入当前bucket,那就需要再构建一个新的溢出桶 bucket,并通过overflow指针连接起来,使得bucket形成一个链表结构。 - 存储key/value的数组
keys
、values
- 高位哈希值
- 而对于其中的
二、key-value是如何存放的:
当前bucket桶中的 key-value 的值的存放是有其特点的,bucket桶中所有的key存放到 keys
数组中,而所有的value存放到 values
数组中。
这么做的原因也很简单,可以在key和value的长度不同时,消除padding(内存对齐)带来的空间浪费。具体如图所示:
三、根据key 查找/新增 数据:
对传来的key进行哈希运算得到唯一哈希值,并将该哈希值分为高位和低位,如图所示:
蓝色为高位,红色为低位。 低位用于寻找当前key属于哪个bucket,而高位用于寻找对应bucket中的具体key。
而之前 bmap
中的高位哈希值数组字段 topbits
,存的就是当前bucket桶中不同key-value键值对中对应key的高位哈希值,这样便于根据key查找数据。
新增的过程与查找过程类似,也是填充桶的过程。
四、删除map中的数据
针对map中的key-value数据:
- 如果是指针类型数据,则将其原有引用去除,利用go GC来清理内存
- 如果是值类型数据,则直接清理对应内存空间
最后将该key-value记录对应的 【bmap
中高位哈希值数组 topbits
】中的key相关 “索引” 置空。
五、map的扩容
当go map中每个bucket桶存储的平均元素个数大于加载因子 loadFactor = 6.5
(判断扩容的条件)时,map底层就会创建一个容量大小是原来2倍的新buckets数组,并将 oldbuckets
指针指向原来的旧buckets数组。然后,对旧buckets数组中的元素key重新哈希(rehash)得到新的哈希值,根据新的哈希值的高位和低位来放入扩容后的新buckets数组中。
加载因子越小↓,说明空间利用率低,因此 “产生冲突的机会” 低;
加载因子越大↑,说明空间利用率高,但是 “产生冲突的机会” 也高了。
不过需要注意的是:
并不是立刻把 oldbuckets
指针所指向的旧bucket数组中的元素一次性转移到新的bucket数组当中,而是当只有访问到具体某个key所在的bucket时,才会将该bucket中的旧数据逐步迁移到新bucket中。一直到旧数据完全迁移完,才会删除 oldbuckets
的指向,使得旧buckets空间得到释放。如下图所示:
这里迁移完并不会直接删除旧bucket中的数据,而是把原来旧数据的引用去掉,利用GC逐步清除内存。
六、map的等量扩容(缩容)
map中数据较少,但 overflow
指向的溢出桶bucket数量过多时,会导致溢出桶中的记录存储很稀疏,排列不紧凑,大量空间被浪费。这时就需要进行等量扩容/缩容(一般出现在之前数据被大量删除的场景下)。
其实就是重新整理一下数据,使溢出桶中的数据重新紧凑的放在普通bucket桶中,避免不必要的空间浪费。
相关文章:

Golang Map原理(底层结构、查找/新增/删除、扩缩容)
参考: 解剖Go语言map底层实现Go语言核心手册-3.字典 一、Go Map底层结构: Go map的底层实现是一个哈希表(数组 链表),使用拉链法消除哈希冲突,因此实现map的过程实际上就是实现哈希表的过程。 先来看下…...

Java_数组
数组 1.概念 需求:现在需要统计软件技术1班47名同学的成绩情况,例如计算平均成绩、最高成绩等。如果只能使用变量的话,那么需要定义100个变量,这样就比较复杂了。这时我们就可以使用数组来记住这47名同学的成绩,然…...
list与vector的区别
相信大家已经学过list与vector,关于它们的不同,我做了一些总结,如下表: vector list底层结构动态顺序表,一段连续的空间带头结点的双向链表随机访问支持随机访问,访问某个元素的效率…...

【C++、数据结构】位图、布隆过滤器、哈希切割(哈希思想的应用)
文章目录📖 前言1. 位图1.1 海量数据处理思路分析:1.2 位图的具体实现:1.3 用位图解决问题:应用一:应用二:应用三:2. 布隆过滤器2.1 布隆过滤器的概念:2.2 布隆过滤器的测试…...

计算机网络安全基础知识3:网站漏洞,安装phpstudy,安装靶场漏洞DVWA,搭建一个网站
计算机网络安全基础知识3:网站漏洞,安装phpstudy,安装靶场漏洞DVWA,搭建一个网站 2022找工作是学历、能力和运气的超强结合体,遇到寒冬,大厂不招人,可能很多算法学生都得去找开发,测…...

大话数据结构-迪杰斯特拉算法(Dijkstra)和弗洛伊德算法(Floyd)
6 最短路径 最短路径,对于图来说,是两顶点之间经过的边数最少的路径;对于网来说,是指两顶点之间经过的边上权值之和最小的路径。路径上第一个顶点为源点,最后一个顶点是终点。 6.1 迪杰斯特拉(Dijkstra&am…...
2023年全国最新食品安全管理员精选真题及答案10
百分百题库提供食品安全管理员考试试题、食品安全员考试预测题、食品安全管理员考试真题、食品安全员证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。 91.实施日常检查,如果违反关键项的,应当即作出如…...

Unity常见面试题详解(持续更新...)
一丶声明、定义、实例化、初始化 1、首先我们来讨论在C/C中的声明和定义.. 1)我们先从函数声明和定义说起... 一般我们在C里都会先定义一个函数,然后再Main函数前将函数声明,比如: //函数声明 int Add(int);int Main {} //函数…...

java高级篇之三大性质总结:原子性、可见性以及有序性
1. 三大性质简介 在并发编程中分析线程安全的问题时往往需要切入点,那就是两大核心:JMM抽象内存模型以及happens-before规则(在这篇文章中已经经过了),三条性质:原子性,有序性和可见性。关于sy…...

真涨脸,我用 Python 为朋友自动化整理表格
今天,在工作的时候,我的美女同事问我有没有办法自动生成一个这样的表格: 第一列是院校科目,第二列是年份,第三列是数量。 这张表格是基于这一文件夹填充的,之前要一个文件夹一个文件夹打开然后手动填写年份…...

MySQL学习笔记(1.操作数据库与数据的SQL)
1. 下载安装 参照:MySQL8.0下载安装_凯尔萨厮的博客-CSDN博客 2. MySQL启动与停止 方式(1).我的电脑>右键>管理>服务和应用程序>服务>(或在windows搜索栏输入services.msc) 找到MySQL80,右键启动或停止 方式(2…...

C++——特殊类设计
目录 不能被拷贝的类 只能在堆上创建对象的类 只能在栈上创建对象的类 不能被继承的类 只能创建一个对象的类(单例模式) 饿汉模式 懒汉模式 单例对象释放问题 不能被拷贝的类 C98:将拷贝构造函数与赋值运算符重载只声明不定义,并且将其访问权…...
Scratch少儿编程案例-植物大战僵尸-趣味角色版
专栏分享 点击跳转=>Unity3D特效百例点击跳转=>案例项目实战源码点击跳转=>游戏脚本-辅助自动化点击跳转=>Android控件全解手册点击跳转=>Scratch编程案例👉关于作者...
Vue的路由守卫
对于绝大部分的网站而言,都是有个人主页的,但是你如果没登陆的话,还能访问个人主页吗? 从逻辑上来讲,那肯定是不行的。 所以,要怎么阻止没登录状态下去访问个人主页呢? 就是利用路由守卫&#x…...
【算法】151. 反转字符串中的单词
链接:https://leetcode.cn/problems/reverse-words-in-a-string/给你一个字符串 s ,请你反转字符串中 单词 的顺序。单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。返回 单词 顺序颠倒且 单词 之间用单个空格连接的结…...
Azure AI基础到实战(C#2022)-认知服务(2)
目录 ComputerVisionClient Class定义构造函数属性上一节例子Task.Wait 方法其它部分分析winform调用认知服务代码剖析1、调用参数2、定义ComputerVisionClient对象,准备调用 REST API3、Authenticate4、调用REST API,这是重点和关键(1)Lambda 表达式和匿名函数(2)async(3)…...

并发就一定快吗?答:肯定不是啊
文章目录一、多线程概念1.1 程序的并发与并行1.1.1 程序的并行1.1.2 程序的并发1.2 进程与线程1.2.1 进程1.2.2 线程1.2.3 多线程并发就一定快吗?答案直接戳这里👉:多线程并发就一定快吗? 一、多线程概念 在实际应用中ÿ…...
前端的学习路线和方法
一些前端工程师面临的现状 1.没有系统的的学习基础知识 2.技术上存在短板,说句不好听的话,大多数开发者的上升通道都没有明确的路线,大公司还好,小公司基本都是后端作为开发组组长 3.前端各种技术层出不穷,需要花费…...

用C语言写一个自己的shell-Part Ⅱ--execute commands
Part Ⅱ–execute commands Exec This brings us to the exec family of functions. Namely, it has the following functions: execlexecvexecleexecveexeclpexecvp For our needs,we will use execvp whose signature looks like this int execvp(const char *file, cha…...

案例实践|运营腾讯游戏,Proxima Beta 使用 Apache Pulsar 升级团队协作与数据治理...
文章摘要本文整理自 Pulsar Summit Asia 2022 上,Proxima Beta 软件工程师施磊的分享《How to achieve better team integration and data governance by using Apache Pulsar》。本文首先将为大家介绍 CQRS 和 Event Sourcing 概念,便于了解为何 Proxim…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...

R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...

免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...