golang中的哈希表 | 青训营笔记

66 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天

map

Go语言中的map又被叫做hash表,使用频率极高,原理是将(key,value)中的key使用hash函数算出对应的值储存在buckets桶中,在绝大多数情况下,哈希表的查询速度明显快于一些搜索树,被广泛用于缓存,数据库缓存中,下面带大家看一下map的几种定义方法

var hash map[T]T
var hash = make(map[T]T,num) //T是类型,num为初始大小
hash := make(map[T]T,num)
var hash = map[string]string{
    "xiaohan" : "hello",
    "xiaozhu" : "world",
    "xiaohui" : "lunch",
    } //创建时添加元素

map有两种访问方法:

v := map[key] //拿到值,如果对应的key不存在,那么返回对应类型的零值
v,ok := map[key] //不存在ok为false

map可以使用delete关键字进行删除key,例如delete(hash,k1),delete可以对相同的key多次删除不会报错 在golang中,map是不支持并发读写的,在官方文档的解释中,map不需要从多个goroutine中进行安全访问,如果加锁的话会减慢大量程序的速度,当我们需要使用安全的map时,可以使用sync包下面的sync.Map,这个是并发安全的map。

下面来看一下map的底层实现

type hmap struct{
    count   int            //记录元素的数量
    flags   uint8          //是否处于正在写入的状态
    B       uint8          //有2^B个桶
    buckets unsafe.Pointer //指向当前map对应的桶指针
    ......
    extra   *mapextra      //储存map中的溢出桶
    }

map中每一个桶中存储8个k,v,当桶中的数据超过八个时,会将新数据放置到溢出桶中,当map超过了负载因子的大小或者溢出桶的数量过多的话,map会进行重建

map是一个简单高效的KV存储数据结构,增删改查的方法简单,但是要记住许多特性,比如只有可比较的类型才能作为key,尽量在初始化时评估并指定放入map的数据大小,从而减少重建需要的性能损耗