GO语言之map

什么是map

简单地说,map是一种通过key来获取value的一个数据结构,其底层存储方式为数组,其中,key值不可重复。我们可以通过map[key]来获取value,也可以通过range来遍历map的key和value。

什么是哈希冲突

map中的key是通过类似hash&(len-1)获取的,其中hash为哈希方法,len为数组长度(为2的指数次方)。简单来说,通过上面的运算,可以将key值较为均匀地分布在数组中。如果两个key值通过计算得到的结果一样,即发生哈希冲突。

哈希冲突解决办法
  • 开放定址法:也就是说当我们存储一个key,value时,发现hashkey(key)的下标已经被别key占用,那我们在这个数组中空间中重新找一个没被占用的存储这个冲突的key,那么没被占用的有很多,找哪个好呢?常见的有线性探测法,线性补偿探测法,随机探测法等。
  • 拉链法:何为拉链,简单理解为链表,当key的hash冲突时,我们在冲突位置的元素上形成一个链表,通过指针互连接,当查找时,发现key冲突,顺着链表一直往下找,直到链表的尾节点,找不到则返回空。
  • 二者优略:
    • 拉链法比线性探测法处理简单
    • 线性探测查找是会被拉链法会更消耗时间
    • 线性探测会更加容易导致扩容,而拉链不会
    • 拉链存储了指针,所以空间上会比线性探测占用多一点
    • 拉链是动态申请存储空间的,所以更适合链长不确定的
  • GO语言采用的是拉链法来解决哈希冲突
GO map结构

Go map会在编译阶段转换成runtime包中的hmap,具体的结构请参考源码。其中,bmap指向存储key-value的结构(数组)。数组元素为“桶”,每个桶中包含高8位的hash和相应的8个key-value,高8位hash用来快速找到目标key,其次是8个key,8个value(key和value分开存储,是为了防止key存储空间大于value时,value会自动占用key大小的空间,这样做可以减少空间的浪费),最后是指向溢出桶的指针(解决哈希冲突)。

Go key值范围

map中,key 的类型是受限的,而 val 的类型可以是任意类型。在 map中查找某个 key 的 value,我们需要传递 key 给这个 map,map 会先使用 hash 函数把 key 转换为 hash 值,hash 表通过 hash 值的低几位(原理是对数组长度取余,但通常采用与运算来加速)去查找 hash 桶,然后在去查找到的 hash 桶中查找高8位的hash,快速锁定key,知道key,就可以获取其value了。
如果遇到哈希冲突,即不同key产生的hash值一样,如此就需要额外进行key值的比较,这就要求存储的key值是可以比较相等的,即"=="。在go语言中,有以下几种是不可以判等的。

  • func
  • map
  • slice

对于struct结构体,不同的结构是不可以比较的,但相同的结构体可以比较。由于结构体比较的是内部数据,所以如果结构体包含不可比较的func、map、slice,那么它也是不可以被比较的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值