Golang学习笔记-map

LegendGo · · 921 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

之前在面试今日头条时被问到了map的实现原理,当时答的不是很好。现在从网上找了些资料记录下map的实现原理。

什么是map

map 是一种通过key来获取value的数据结构,其底层存储方式为数组,在存储时 key不能重复,当key重复的时候,value进行覆盖,我们通过key进行hash计算,然后对数组的长度取余,得到key存储在数组的哪个下标位置,最后将key和value转化为一个结构体,放到数组的下标中。

hash冲突

在key进行hash的时候,会出现hash冲突的问题,主要有下面几个解决办法

开放定址法

在存储key-value的时候发现hashkey(key)的下标已经被别key占用,那我们在这个数组中空间中重新找一个没被占用的存储这个冲突的key,那么没被占用的有很多,找哪个好呢?常见的有线性探测法,线性补偿探测法,随机探测法,这里我们主要说一下线性探测法。

  • 线性探测:从冲突的地方向下探测,直到找到一个空位置来存储这个key,当数组都找不到的情况下,会进行扩容。
  • 拉链法:当出现冲突的时候,会在冲突的位置生成一个链表,通过指针相互链接,当查找冲突的时候,就顺着链表一直往下找。

Golang中map的实现原理

在go中,map是用来进行数据存储的,每个数组下标处存储的是一个bucket,这个bucket的类型如下

type bmap {
    tophash [bucketCnt]uint8
}

tophash 用来快速查找key值是否在在bucket中,不是每次都是通过真值进行比较,至于kv的存放,不是k1v1,k2v2,而是k1k2,v1v2,主要是因为map[int64]int8,key是int64(8字节),value是int8(一个字节), key和value的长度不同,如果按照kv格式来存数据,则会占用较多的内存。
最后分析下go的整体内存结构,当向map中写入数据的时候,通过k获取hash值,hash值的低八位和bucket数组长度取余,定位到在数组中的那个下标,hash值的高八位存储在bucket中的tophash中,用来快速判断key是否存在,key和value的具体值则通过指针运算存储,当一个bucket满时,通过overfolw指针链接到下一个bucket。


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:LegendGo

查看原文:Golang学习笔记-map

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

921 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传