go语言map系列(一)

「这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战」。

前言

哈希表也是一个常见的数据结构,通过Hash(key)来寻找对应的value。虽然不能随机搜索,但是可以针对指定的key进行搜索

哈希碰撞

go语言的map底层结构是桶,通过Hash(key)来找对应的桶,这样就会有两个Hash(key1),Hash(key2)的值相同的情况,也就是哈希碰撞。为了避免哈希碰撞,一般有两种方式,拉链法和开放寻址法。拉链法就是桶中存储链表,但这样数据结构就变得更加复杂,而且链表本身搜索速度也会差一些。第二种方式就是开放寻址法,通过某种寻址方法(比如说n = n+1,线性探测)再重新找到一个地址,直到该地址并没有元素存储。出于CPU缓存的角度,我们一般也会选择线性探测。

map的使用方式

初始化

  • 一般来说map声明最好为其初始化,或者使用如下方式,未经初始化的map会在插入操作时报panic
mp := make(map[int64]int64)
复制代码

查询和删除

  • 查询时可以通过v,ok :=mp[key] 的方式判断是否为空,
  • 删除时使用delete(mp,key)

不可并发读写

出于查找效率考虑,map本身并不支持并发读写,但是会支持并发读取。

map底层结构

type hmap struct {
   count     int 
   flags     uint8
   B         uint8 
   noverflow uint16 
   hash0     uint32 
   buckets    unsafe.Pointer 
   oldbuckets unsafe.Pointer 
   nevacuate  uintptr       
   extra *mapextra 
}
复制代码

hmap中有指向桶的指针buckets,通过指针计算获取对应桶的位置,并根据hash前八位值,定位具体的k,v对。如果为nil可能代表这个hmap未初始化。(也可以根据count值判断)

总结

本文介绍了map结构,及其对应的增删改查操作。下篇文章剖析底层设计。

Guess you like

Origin juejin.im/post/7066820393339715620