golang中map原理剖析
1. golang中的map有自己的一套实现原理,其核心是由hmap和bmap两个结构体实现的

2. 初始化map
package main
func main() {
// 初始化一个可容纳10个元素的map
map1 := make(map[string]string, 10)
// 第一步:创建一个hmap结构体对象
// 第二步:生成一个哈希因子hash0并赋值到hmap对象中(用于后续为key创建哈希值)
// 第三步:根据hint=10,并根据算法规则来创建B,当前B应该为1
/*
hint B
0~8 0
9~13 1
14~26 2
...
*/
// 第四步:根据B去创建桶(bmap对象)并存在buckets数组中,当前bmap的数量应为2
// 当B<4时,根据B创建桶的个数的规则为:2的B次方(标准通)
// 当B>=4时,根据B创建桶的个数的规则为:2的B次方 + 2的(B-4)次方(标准通+溢出桶)
// 注意:每个bmap中可以存储8个键值对,当不够存时需要使用溢出桶,并将当前bmap中的overflow字段指向溢出桶的位置
}
3. map写入数据
map1["name"] = "武沛齐"
// 第一步:结合哈希因子和键name生成哈希值
// 第二步:取哈希值的后B位,并根据后B位的值来决定将此键值对存放到哪个桶中(bmap)。
/*
将哈希值和桶掩码(B个为1的二进制)进行&运算,最终得到哈希值的后B位的值,假设当B为1时,其结果为0
哈希值:0101001111001011010
桶掩码:0000000000000000001
结果: 0000000000000000000 = 0
通过示例你会发现,找桶的原则实际上是根据后B位的位运算计算出索引位置,然后再去buckets数组中根据索引找到目标桶(bmap)。
*/
// 第三步:在上一步确定桶之后,接下来就在桶中写入数据
/*
获取哈希值的tophash(即:哈希值的'高8位'),将tophash,key,value分别写入到桶中的三个数组中
如果桶已满,则通过overflow找到溢出桶,并在溢出桶中继续写入。‘
注意:以后在桶中查找数据时,会基于tophash来找,(tophash相同则再去比较key)
*/
// 第四步:hmap的个数count++(map中的元素个数+1)
4. map读取数据
value := map1["name"]
// 第一步:结合哈希因子和键name生成哈希值。
// 第二步:获取哈希值的后B位,并根据后B位的值来决定将此键存放到哪个桶中(bmap)。
// 第三步:确定桶之后,在根据key的哈希值计算出tophash(高8位),再根据tophash和key去桶中查找数据。
// 当前桶如果没有找到,则根据overflow在去溢出桶中找,均未找到则表示key不存在
5. map扩容
// 在向map中添加数据时,当达到某个条件,则会引发map扩容
// 扩容条件
// 1. map中数据总个数/桶个数>6.5时,引发翻倍扩容
// 2. 使用了太多的溢出桶时,(溢出桶使用的太多会导致map处理速度降低)
// B <= 15,已使用的溢出桶个数 >=2的B次方时,引发等量扩容
// B > 15,已使用的溢出桶个数 >=2的15次方时,引发等量扩容

6. map中数据迁移



golang中map原理剖析的更多相关文章
- golang 中 map 转 struct
golang 中 map 转 struct package main import ( "fmt" "github.com/goinggo/mapstructure&qu ...
- Golang中map的三种声明方式和简单实现增删改查
package main import ( "fmt" ) func main() { test3 := map[string]string{ "one": & ...
- golang中map并发读写问题及解决方法
一.map并发读写问题 如果map由多协程同时读和写就会出现 fatal error:concurrent map read and map write的错误 如下代码很容易就出现map并发读写问题 ...
- Go_14:GoLang中 json、map、struct 之间的相互转化
1. golang 中 json 转 struct <1. 使用 json.Unmarshal 时,结构体的每一项必须是导出项(import field).也就是说结构体的 key 对应的首字母 ...
- GoLang中 json、map、struct 之间的相互转化
1. golang 中 json 转 struct <1. 使用 json.Unmarshal 时,结构体的每一项必须是导出项(import field).也就是说结构体的 key 对应的首字母 ...
- 说说不知道的Golang中参数传递
本文由云+社区发表 导言 几乎每一个C++开发人员,都被面试过有关于函数参数是值传递还是引用传递的问题,其实不止于C++,任何一个语言中,我们都需要关心函数在参数传递时的行为.在golang中存在着m ...
- golang之map的使用声明
1.map的基本介绍 map是key-value数据结构,又称为字段或者关联数组.类似其它编程语言的集合,在编程中是经常使用到的 2.map的声明 1)基本语法 var map 变量名 map[key ...
- 0000 - Spring 中常用注解原理剖析
1.概述 Spring 框架核心组件之一是 IOC,IOC 则管理 Bean 的创建和 Bean 之间的依赖注入,对于 Bean 的创建可以通过在 XML 里面使用 <bean/> 标签来 ...
- Spring 中常用注解原理剖析
前言 Spring 框架核心组件之一是 IOC,IOC 则管理 Bean 的创建和 Bean 之间的依赖注入,对于 Bean 的创建可以通过在 XML 里面使用 <bean/> 标签来配置 ...
随机推荐
- JAVAWEB进行PC支付宝支付、查询订单支付状态
官方文档:https://opendocs.alipay.com/open/270/105899 本地开发环境支付回调调试方法可以参考:https://www.cnblogs.com/pxblog/p ...
- nim_duilib之virtualListbox用法(22)
概述 本文将介绍virtualListbox的用法. 更多请参考源码. 一个样式 样式丑了点,勿喷. 重写函数 使用virtualListbox, 需要一个派生类(继承自基类VirtualListIn ...
- 【LeetCode】1579. 保证图可完全遍历 Remove Max Number of Edges to Keep Graph Fully Traversable
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题思路 并查集 代码 欢迎加入组织 日期 题目地址:https ...
- 【经验】基于阿里云 Ubuntu 的 LAMP 网站搭建及配置完全教程
本文同步发表在负雪明烛的博客:https://fuxuemingzhu.cn/2016/03/02/My-Aliyun-Server-Setting/ 起因 最近老师让我做一个众筹系统,可以在微信公众 ...
- codeforce 595B-Pasha and Phone(数学)
今天补题,昨天是我太猖狂了,在机房吹牛,然后说着说着忘了时间,后来楼长来了,我们走了,CF没打成. 不扯了,下面说题: 题目的意思是给你n和k, n代表最后得出的号码有n为,然后k能被n整除,就是把n ...
- 业务层面和运维层面优化你的Redis
业务层面 key的长度尽量要短,在数据量非常大时,过长的key名会占用更多的内存; 一定避免存储过大的数据(大value),过大的数据在分配内存和释放内存时耗时严重,会阻塞主线程; Redis 4.0 ...
- 第四十六个知识点 在Sigma协议中,正确性,公正性和零知识性意味着什么
第四十六个知识点 在Sigma协议中,正确性,公正性和零知识性意味着什么 Sigma协议 Sigma协议是Alice想要向Bob证明一些东西的协议(Alice知道一些秘密).他们有下面的一般范式:Al ...
- 「算法笔记」BSGS 与 exBSGS
一.离散对数 给定 \(a,b,m\),存在一个 \(x\),使得 \(\displaystyle a^x\equiv b\pmod m\) 则称 \(x\) 为 \(b\) 在模 \(m\) 意义下 ...
- 剖析Defi之Uinswap_0
Uniswap是什么,不需要讲了吧.YYDS(永远嘀神) 介绍几个概念: 恒定乘积算法:可以简单看作X * Y = K,这里K(乘积)保持不变,所以叫恒定乘积算法,该函数是一个反曲线. 自动流动性协议 ...
- 使用docker或者docker-compose部署Zookeeper集群
之前有介绍过Zookeeper的安装部署(Zookeeper基础教程(二):Zookeeper安装),但是那里我是基于独立的虚拟机来实现部署的,这种部署方式适合线上集群部署.后来有几次想用一下Zook ...