Go Map

news2024/11/15 15:41:27

Go Map

map 是一种key-value的键值对存储结构,其中key不能重复,无序。底层是hmap结构,hmap中维护buckets(bmap结构)

结构定义

type hmap struct {
	count     int // 元素个数
	B         uint8  // buckets已扩容的次数,buckets长度2^B
	noverflow uint16 // 溢出buckets的数量
	hash0     uint32 // hash 种子
	buckets    unsafe.Pointer // 2^B buckets 的数组指针
	oldbuckets unsafe.Pointer // 指向扩容前的buckets的数组指针
	extra *mapextra // 可选字段,额外信息
}
// 额外信息
type mapextra struct {
	overflow    *[]*bmap
	oldoverflow *[]*bmap
	nextOverflow *bmap
}
// 在编译期间会产生新的结构体
type bmap struct {
	tophash [8]uint8 //存储哈希值的高8位
	data    byte[1]  //key value数据:key/key/.../value/value...
    overflow *bmap   //溢出bucket的地址
}

请添加图片描述

  • bmap
backet数组中的每个元素都是bmap结构(本文都称为桶)
每个桶最多保存8个kv对,之后使用overflow连接下一个桶(溢出桶)。
tophash:保存的是key值哈希值的前8位,用作查找key的缓存,确定key是否存在
注:key、value、overflow字段都不显示定义,而是通过maptype计算偏移获取的。
  • 高位hash和低位hash值
哈希函数会将传入的key值进行哈希运算,得到一个唯一的值。

比如key1的hash值为:0123456789876543210      
前八位hash值"01234567"部分就叫做"高位哈希值",后B位hash值为"低位哈希值"

高位哈希值:是用来确定当前的桶有没有所存储的数据的
低位哈希值:是用来确定,当前的数据存在了哪个桶

查询

  1. 根据key值算出哈希值
  2. 取低位哈希值确定在哪号桶
  3. 取高位哈希值在tophash数组中查询,确定在桶中的哪个位置
  4. 对比key完整的哈希值,如匹配获取对应的value
  5. 如没有找到,则从下个溢出桶中查找

存放

  1. 根据key值算出哈希值
  2. 取低位哈希值确定在哪号桶
  3. 取高位哈希值在tophash数组中查询,确定在桶中的哪个位置
  4. 对比key完整的哈希值,如匹配则更新值,不匹配则新增值
  5. 如果当前桶元素已满,会通过overflow链接创建一个新的桶,来存储数据。

低位哈希值确定桶

Go通过'与运算法'来确定桶的位置
公式:hash(k)&(m-1),(m为map长度)
注:桶的数目需是2的整数次幂(m的二进制数不只含一个1),否则会出现有些桶不会被选中

哈希冲突

Go通过'拉链法'来解决hash冲突:线性向下
  • 查询冲突
    冲突原因:第3步找到对应高位哈希值,第4步对比完整哈希值时不同:
    解决方式:线性向下查找key值
  • 存放冲突
    冲突原因:第3步找到对应高位哈希值,第4步对比完整哈希值时不同:
    解决方式:线性向下寻空位插入

负载因子

负载因子用于衡量一个哈希表冲突情况,公式为:负载因子 = 键数量 / 桶数量
  • 哈希因子过小,说明空间利用率低
  • 哈希因子过大,说明冲突严重,存取效率低

扩容

扩容有两种:等量扩容、2倍扩容

前提条件

  1. 负载因子 > 6.5时,也即平均每个桶存储的键值对达到6.5个
  2. 当溢出桶过多时:
    (map不断的put和delete key,桶中可能会出现很多断断续续的空位,会导致连接的bmap溢出桶很长,导致扫描时间边长)
    • 当B < 15 时,overflow的桶数量超过 2^B
    • 当B >= 15 时,overflow的桶数量超过 2^15

等量扩容

前提条件2:这种扩容实际上是一种整理,把后置位的数据整理到前面。这种情况下,元素会发生重排,但不会换桶。

2倍扩容

前提条件1:这种2倍扩容是由于当前桶数组确实不够用了,发生这种扩容时,元素会重排,可能会发生桶迁移。
  • 扩容细节
  1. 扩容刚发生时,会先将老数据存到oldbuckets里面。
  2. 每次对map进行删改操作时,会触发从oldbucket中迁移到bucket的操作【非一次性,分多次】
  3. 在扩容没有完全迁移完成之前,每次get或者put遍历数据时,都会先遍历oldbuckets,然后再遍历buckets。

线程不安全

  • sync.Map
  • map+互斥锁
  • channel
优先使用互斥锁的场景:
1 复杂且频繁的数据读写操作,如:缓存数据;
2 应用中全局的共享数据,如:全局变量;

优先使用channel的场景:
1 协程之间局部传递共享数据,如:订阅发布模式;
2 统一的数据处理服务,如:库存更新+订单处理;

注意

  • 对map数据进行操作时不可取地址,扩容会变
  • map不会发生缩容:反复的扩容缩容会导致泄漏

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

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

相关文章

JVM-Java内存区域

1、运行时数据区域 运行时数据区域&#xff1a;程序计数器、Java虚拟机栈、本地方法栈、堆、方法区。 非运行时数据区域&#xff1a;直接内存。 &#xff08;1&#xff09;程序计数器 字节码解释器通过改变程序计数器来依次读取指令&#xff0c;从而实现代码的流程控制。在多线…

谷歌2022年最受欢迎Chrome浏览器扩展程序:包含Tango,Compose AI等

根据截图排序从左到右依次介绍如下&#xff1a; RoPro&#xff1a;Roblox.com网站体验增加了许多有用且独特的功能&#xff1b; MyBib&#xff1a;自动创建 APA 样式、MLA 格式和哈佛引用样式引文&#xff1b; eJOY English&#xff1a;翻译自Netflix, Youtube, iFlix上的字…

Codeforces Round #841 (Div. 2) and Divide by Zero 2022(A-D)

Codeforces Round #841 (Div. 2) and Divide by Zero 2022&#xff08;A-D&#xff09; 题目链接限制AJoey Takes Moneystandard input/output1 s, 256 MBBKill Demodogsstandard input/output1 s, 256 MBCEven Subarraysstandard input/output2.5 s, 256 MBDValiant’s New M…

数字经济指标构建-各省、地级市匹配上市公司数据、城市数字化指数

一、中国城市数字经济指数2017-2022年&#xff08;数据代码报告&#xff09; 中国城市数字化指数全面覆盖城市数字化规划、建设、运营的各个方面&#xff0c;能够有效评估城市各个领域的数字化建设水平和运营效果。 全国城市数字经济发展热图 数据来源&#xff1a;中国城市数字…

语音转换之CycleGan-VC2:原理与实战

非平行语音转换CycleGAN 之前学习了传统统计学习里的经典的语音转换模型GMM。随着深度学习的发展&#xff0c;出现了更好的语音转换方法&#xff0c;今天学习较为经典的CycleGan。 平行语音转换一般流程 典型代表就是基于GMM的语音转换。平行数据就是说源语音和目标语音一一…

矢量图斑局部狭长判断和定位局部狭长部分(PostGIS、Java、C#实现)

矢量数据在数据采集过程中由于数据处理导致出现局部狭窄的面状部分&#xff0c;如下图 1. 定义和解决方法 狭长结构是指图斑几何形态上窄而长的部分,符号化后出现图形粘连压盖现象,导致难以在图面上清晰地表达出来。因此,依据地图表达比例尺因素需要对狭长结构进行融解处理。在…

helm部署frps和连接

文章目录一. helm部署frps1.1 下载1.2 部署1.2.1 不开启dashboard界面1.2.2 开启dashboard界面1.2.3 卸载1.3 查看1.4 IP Port 允许端口1.5 Web Ingress二. frpc客户端连接2.1 IP Port 连接2.2 Web 域名连接一. helm部署frps 1.1 下载 mkdir -p /root/i/helm && cd…

并查集专题1_图篇

1.并查集介绍 并查集支持查询和合并操作&#xff0c;只回答两个节点是不是在一个连通分量中&#xff0c;并不回答路径问题。 如果一个问题具有传递性&#xff0c;可以考虑用并查集。并查集最常见的一种设计思想是把在同一个连通分量中的节点组织成一个树形结构。 2.并查集的…

动作捕捉技术应用于地面移动机器人协同

《一千零一夜》故事集中收录的《阿拉丁神灯》深受读者们的喜爱&#xff0c;其中阿拉丁拥有一块神奇的魔毯&#xff0c;它具有运载功能&#xff0c;可以将物体轻松便捷的从一个地方转移到另一个地方。在现实生活中&#xff0c;可变形布作为一种轻量便携且具有良好适应性的载体&a…

redhat9中mysql常用命令(持续更新)

目录 1、查看当前用户 2、查看选择的数据库 3、创建数据库 4、创建数据表 5、插入数据 6、查看表所以字段的内容 7、查看数据库当前密码策略 8、查看密码插件 9、更改密码策略为LOW&#xff0c;改为LOW或0 10、 更改密码长度 11、设置大小写、数字和特殊字符均不要求 …

微服务系列专栏介绍

文章目录一 专栏介绍1.1 微服务行业背景不同行业IT系统更新频率IT系统存在的问题微服务架构在企业中应用情况1.2 什么是微服务1.3 微服务的特点1.4 微服务诞生背景1.5 微服务架构的优势二 专栏目标三 专栏涉及技术四 专栏架构1.微服务架构&#xff1a;2.Go语言3.go-micro架构4.…

入侵无线WiFi的主要方式及防护要点

从攻击形态上看&#xff0c;无线网络攻击主要可以分为三个大类&#xff1a;被动型攻击、主动型攻击以及针对网络组件的攻击&#xff1a; 被动攻击一般发生在攻击者处于无线网络范围内并可以监视无线通信内容时&#xff0c;最常见的被动攻击是数据包嗅探。由于被动攻击者只是监…

HTTPS 的通信加解密过程,证书为什么更安全?

经典面试题 HTTPS 的通信加解密过程&#xff0c;证书为什么更安全&#xff1f; 考察点 《计算机网络》相关知识 了解 HTTPS 协议加解密的过程 了解数字证书认证的过程 技术点 对称加密和非对称加密 HTTPS 协议的加解密过程 数字证书认证过程 对称加密和非对称加密 对称加…

Mysql 小Tips

Mysql 小Tips 目录Mysql 小Tips1.group_concat2.char_length3.locate4.replace5.now6.insert into ... select7.insert into ... ignore8.select ... for update9.on duplicate key update10.show create table11.create table ... select12.explain13.show processlist14.mysq…

企业电子招投标采购系统源码之首页设计

​ 功能模块&#xff1a; 待办消息&#xff0c;招标公告&#xff0c;中标公告&#xff0c;信息发布 描述&#xff1a; 全过程数字化采购管理&#xff0c;打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力&#xff0c;为外…

字符设备驱动(二)

1. IO模型 &#xff08;1&#xff09;阻塞式IO&#xff1a;不能操作就睡觉 &#xff08;2&#xff09;非阻塞式IO&#xff1a;不能操作就返回错误 &#xff08;3&#xff09;IO复用 &#xff08;4&#xff09;信号驱动式IO &#xff08;5&#xff09;异步IO 2.阻塞与…

c++算法基础必刷题目——按位贪心

文章目录按位贪心1、毒瘤xor2、兔子的区间密码3、起床困难综合症按位贪心 1、毒瘤xor NC18979 毒瘤xor 题目描述 小a有N个数a1, a2, …, aN&#xff0c;给出q个询问&#xff0c;每次询问给出区间[L, R]&#xff0c;现在请你找到一个数X&#xff0c;使得 1、0⩽X<231 2、∑…

Vue(ref和$refs属性介绍与使用)

一、 Vue(ref和$refs属性介绍与使用) 在Vue中一般很少会用到直接操作DOM&#xff0c;但不可避免有时候需要用到&#xff0c;这时我们可以通过ref和$refs这两个来实现&#xff0c;本文我们就来详细的介绍下这个内容 除了自定义属性外&#xff0c;Vue实例还暴露一些有用的实例属性…

Educational Codeforces Round 140 (Rated for Div. 2)

A. Cut the Triangle 题目链接&#xff1a;Problem - A - Codeforces 样例输入&#xff1a; 44 7 6 8 3 54 5 4 7 6 85 8 1 8 2 53 6 6 6 6 3 样例输出&#xff1a; YES YES YES NO题意&#xff1a;在二维平面上给定一个非退化三角形的三个顶点&#xff0c;问我们能不能用…

NVIDA CUDA和cuDNN安装教程

文章目录一. 查看自己的GPU版本是否支持cuda二 .安装CUDA三. 安装cuDNN一. 查看自己的GPU版本是否支持cuda 打开显卡的控制面板&#xff0c;查看显卡是否支持cuda 二 .安装CUDA 去官网查看cuda版本与所需系统固件的对应关系 从官网下载所需的CUDA Toolkit Archive,这里下载…