Golang Map 基本原理

news2024/12/23 22:34:33

Go 语言中的 map 即哈希表。哈希表把元素分到多个桶里,每个桶里最多放8个元素。在访问元素时,首先用哈希算法根据 key 和哈希表种子获得哈希值(暂将其命名为 h),然后利用 h 的低 b b b 位得到桶的序号。其中桶的个数为 2 b 2^b 2b 个,是 2 的幂。桶中存储了所有元素的 key、value 和 key 哈希值的高 8 位。所以在找到桶之后会遍历元素的高 8 位哈希值,判断与 h 的高 8 位哈希值是否相等,若相等则再对比 key。如果在当前桶中没有找到 key,还会与溢出桶的元素进行比较。

在哈希表的数据结构中,结构体 hmap 是哈希表的核心,里面记录了一些元数据,例如元素数据、桶的数量、哈希表种子,还有用于储存数据的 buckets 数据。

type hmap struct {
/**元数据**/
  count int // 哈希表元素数量
  B int // 2^B=桶的个数 
  hash0 uint32 // 哈希表种子,在创建哈希表时确定
/**存储**/
  buckets []bmap // 桶,一个桶中最多有8个元素
  mapextra struct { // 溢出桶
    overflow *[]*bmap // 非预分配的溢出桶
    nextOverflow *bmap // 指向预创建的溢出桶 
  }
}

bmap 是桶的结构,里面存储了每个元素的 key、value 和哈希值的高 8 位。

type bmap struct {
    topbits [8]uint8 // 哈希值高 8 位
    keys [8]keytype // 存储key
    values [8]valuetype // 存储value
    overflow *bmap
}

哈希表的逻辑结构是正常桶和溢出桶组成链表,但其内存结构是正常桶与预创建的溢出桶在连续的内存空间中,其它溢出桶在需要时才会创建,内存不连续。

map 的逻辑结构

map 的创建过程:首先根据 make(map[keytype]valuetype, cap) 中传入的容量计算出桶的个数,计算规则是找出最大的 B B B 使得 cap > 6.5 ∗ 2 B \text{cap} > 6.5 * 2^B cap>6.52B,其中 6.5 是装载因子,表示平均一个桶里面放多少个元素。其中的 B B B 代表正常桶的个数,在创建 2 B 2^B 2B 个正常桶时,还要创建 2 B − 4 2^{B-4} 2B4 个溢出桶,因为可能会出现哈希函数产生了不均匀的哈希值,导致一个桶序号中包含的元素不止 8 个。

新增元素过程:如果新增的元素不存在于当前哈希表中,则把元素添加到正常桶中,如果正常桶满了,就尝试添加到溢出桶中,如果溢出桶也满了,则创建新的溢出桶。

扩容过程包含两步,首先创建一组新桶,然后迁移数据。新桶的大小由两个因素决定,如果装载因子超过 6.5,则容量翻倍,如果只是溢出桶太多,则容量不变。溢出桶多通常发生在向 map 中添加了很多元素后来又删掉的情况,容量不变的意义是将溢出桶中的数据“放回”正常桶中,不过不是放回原来的正常桶,而是放到新建的桶中。

在为新桶分配好内存后且在迁移数据之前会用 hmap.oldbuckets 指向旧桶。当有新的访问请求时优先访问旧桶,如果旧桶已迁移才会访问新桶。迁移数据的过程是惰性的,只有在 map 赋值或者删除时才会触发数据迁移,并且值迁移当前桶即对应的溢出桶,比如在 delete(map, key) 时计算出桶序号是 2,在旧桶大小为 4 的情况下,会把 2 号桶即其溢出桶根据哈希值复制到新 2 号和新 6 号桶中。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

乐趣国学—品读“富润屋,德润身。”中的智慧

✅作者简介:热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 ✨当前专栏:国学周更-心性养成之路 …

java 基于 SpringMVC+Mybaties+ easyUI 快递公司管理系统 的 设计与实现

一.项目介绍 本系统 角色 权限 动态配置 默认配置了三种 第一种: 超级管理员 第二种: 运输公司 第三种: 订单跟踪人员 超级管理员拥有所有权限,包括车子、路线、订单、是否送达以及交易的统计报表 运输公司:车辆管理权…

使用 Python 和 Streamlit 创建一个很棒的 Web 应用程序

“我们如何制作一个机器学习脚本并将其转换为一个尽可能简单的应用程序,让它基本上感觉像是一个脚本练习?” — Adrien Treuille(Streamlit 的发明者) Web 应用程序是显示数据科学或机器学习项目结果的好方法。从头开始开发 Web 应用程序需要大量时间、精力和技术技能。另一…

世界杯海信再出圈,三星:“谈不上愉悦”

作者 | 曾响铃 文 | 响铃说 本届世界杯作为第一次在北半球冬季举行的世界杯,给全世界球迷带去了一次全新体验。且随着赛程的推进,更多的“惊喜”也一一浮现。 其一便是超多的爆冷,虽然没有具体统计,但此次应该是近几届爆冷最多…

[激光原理与应用-32]:典型激光器 -4- 半导体泵浦固体激光器

目录 第1章 概述 1.1 什么是半导体泵浦固体激光器 1.2 优势 1.3 典型的波长 第2章 半导体泵浦固体激光器的种类 2.1 端面泵浦固体激光器 2.2 侧面泵浦固体激光器 第1章 概述 1.1 什么是半导体泵浦固体激光器 半导体泵浦固体激光器(Diode Pump Solid State …

Python函数

一、函数介绍 函数:是组织好的,可重复使用的,用来实现特定功能的代码段。 使用函数的好处是: 将功能封装在函数内,可供随时随地重复利用提高代码的复用性,减少重复代码,提高开发效率二、函数…

学习python第一天

关于Python的数据类型 Python数据类型包括: 数字类型,字符类型,布尔类型,空类型,列表类型,元组类型,字典类型 1、数字类型 包括:整型int 浮点型float(有小数位的都是是浮点型) 注…

代码随想录刷题|LeetCode 1143.最长公共子序列 1035.不相交的线 53. 最大子序和 动态规划

目录 1143.最长公共子序列 思路 1、确定dp数组 2、确定递推公式 3、dp数组初始化 4、遍历顺序 5、推导dp数组 最长公共子序列 1035.不相交的线 思路 不相交的线 53. 最大子序和 思路 最大子序列 动态规划 贪心算法 1143.最长公共子序列 题目链接:力扣 思路 不知道…

你在终端启动的进程,最后都是什么下场?(下)

你在终端启动的进程,最后都是什么下场?(下) 在上期文章你在终端启动的进程,最后都是什么下场?(上)当中我们介绍了前台进程最终结束的几种情况,在本篇文章当中主要给大家…

好书分享丨区块链的骨骼——密码技术

开放隐私计算 开放隐私计算 开放隐私计算OpenMPC是国内第一个且影响力最大的隐私计算开放社区。社区秉承开放共享的精神,专注于隐私计算行业的研究与布道。社区致力于隐私计算技术的传播,愿成为中国 “隐私计算最后一公里的服务区”。 180篇原创内容 …

darknet框架GPU编译安装

Darknet: Open Source Neural Networks in C 1、darknet下载 git clone https://github.com/pjreddie/darknet.git cd darknet设置makefile gpu1 cudnn1 opencv1【1】GPU1;需要设置显卡驱动、cuda 使用nvidia-smi 查看显卡型号和支持的cuda版本号 nvidia官网下载cuda,以及…

计算机网络学习笔记(Ⅱ):物理层

目录 1 物理层概念 1.1 物理层基本概念 1.定义 2.主要任务 3.特性 1.2 数据通信基础 1.典型模型 2.相关术语 3.三种通信方式 4.数据传输方式 1.3 物理层内容 1.码元 2.速率 3.带宽 1.4 奈氏准则与香农定理 1.失真 2.码间串扰 3.奈氏准则 4.香农定理 1.5 …

蓝桥杯C/C++VIP试题每日一练之Huffman树

💛作者主页:静Yu 🧡简介:CSDN全栈优质创作者、华为云享专家、阿里云社区博客专家,前端知识交流社区创建者 💛社区地址:前端知识交流社区 🧡博主的个人博客:静Yu的个人博客 🧡博主的个人笔记本:前端面试题 个人笔记本只记录前端领域的面试题目,项目总结,面试技…

基于JSP的某餐厅点餐系统

目 录 第一章 绪论 1 1.1系统研究背景和意义 1 1.2研究现状 1 1.3研究主要内容 2 第二章 相关技术说明 3 2.1 JSP(Java Server Page)简介 3 2.2 Spring框架简介 4 2.3 Spring MVC框架简介 5 2.4 MyBatis 框架简介 5 2.4 MySql数据库简介 6 2.6 Tomcat简介 7 2.7 jQuery简介 8 …

Hadoop原理与技术——Hbase的基本操作

点击链接查看文档 一、实验目的 上机实操,熟悉指令操作Hbase和java代码操作Hbase 二、实验环境 Windows 10 VMware Workstation Pro虚拟机 Hadoop环境 Jdk1.8 三、实验内容 1:指令操作Hbase (1):start-all.sh,启动所有进程 (2)…

Ansys(Maxwell、Simplorer)与Simulink联合仿真(二)直线电机

Ansys(Maxwell、Simplorer)与Simulink联合仿真(二)直线电机 在仿真过程中,遇到了一个问题,卡了好久得到了解决。 关于 motion setup 提示 moving 找不到面 cannot find the sarface 所有的动态部件要隔开…

【pen200-lab】10.11.1.21(实际获得22权限)

pen200-lab 学习笔记 【pen200-lab】10.11.1.21 🔥系列专栏:pen200-lab 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 📆首发时间:🌴2022年11月27日🌴 🍭作…

算法导论24章单源最短路径—Bellman-Ford算法 Dijkstra算法

松弛操作 松弛操作就是判断从现在s到v的路径更近,还是我从s到u再到v更近,选一个更近的走。 松弛操作的例子 松弛是唯一导致最短路径估计和前驱结点变化的操作 Bellman-Ford算法 第一个循环,循环V-1次,每次循环对所有的边都松弛一…

Python数据分析-matplotlib

目录 一、折线图:plt.plot() 1.1 plt.plot()基本用法 1.2 设置坐标轴范围:plt.axis([xmin,xmax,ymin,ymax]) 1.3 plt.plot()绘制多个图形 1.4 linewidth设置线条宽度 1.5 使用plt.plot()的返回值设置线条属性 1.6 plt.setp()修改线条性质 1.7 对…

软件测试的几种方法

1、从是否关心内部结构来看 (1)白盒测试:又称为结构测试或逻辑驱动测试,是一种按照程序内部逻辑结构和编码结构,设计测试数据并完成测试的一种测试方法。 (2)黑盒测试:又称为数据驱动测试,把测试对象当做看不见的黑盒…