golang map原理

map的实现原理

map的定义

map是由一组key,value键值对组成的抽象数据结构,并且同一个key
只会出现一次。

常见map操作

  1. add增加 k-v
  2. remove删除 k-v
  3. reassign修改 k-v
  4. lookup查询 k-v
    增删改查的操作。

golang里的map结构

主要有两种数据结构

  • 哈希查找表Hashtable
    哈希查找表用一个哈希函数将key分配到不同的桶。
    哈希查找表一般会存在碰撞问题,简而言之,不同的key被哈希分到了同一个桶里面。
    一般有两种解决方式
  1. 链表法
    链表顾名思义,讲桶bucket实现成一个链表,落在同一个桶中的key都会插入这个链表。
  2. 开放地址法
    碰撞发生后,通过一定的规律,在数组的后面挑选空位,用来放置新的key
  • 搜索树searchtree
  1. 平衡搜索树 AVL树,红黑树。
    便利自平衡搜索树,返回的key序列,一般会按照大小从小到大的顺序,而哈希查找表是乱序的。

map的底层实现

go语言底层是采用链表法来解决hash冲突的。


type hmap struct {
    count int
    flags uint8
    B uint8 // 是buckets数组的长度的对数,
    // 也就是说Buckets的数组长度就是2^B
    noverflow uint16
    hash0 uint32
    buckets unsafe.Pointer
    oldbuckets unsafe.Pointer
    nevacuate uintptr
    extra *mapextra
}

bucket里面存储了key value
buckets 是一个指针
它指向一个结构体


typebmapstruct {
    tophash[bucketCnt] uint8
}

typebmapstruct {
    topbits [8]uint8
    keys [8]keytype
    value[8]valuetype
    pad uintptr
    overflow uintptr
}

这里的bmap就是桶
桶里面有8个key这些key之所以会落入同一个桶,是因为他们通过哈希计算后,哈希结果是一类的。

可以遍历的同时删除不

都知道map是一个不安全的数据结构。同时读写会被检测,直接Panic。多个线程的时候。
单个协程,就检测不到了。但是便利的结果可能不会是相同的。一般而言可以通过sync.RWMutex来解决。

可以对map内的元素取地址吗

无法对map的key的value 取地址
因为一旦发生扩容,之前的key,value值就会改变,之前的地址也就不一样了。

如何比较两个map

前提条件

  1. 都为nil
  2. 非空、长度相等、指向同一个map实体对象
  3. 相应的key指向的value深度相等
    需要便利每个key value元素比较是否深度相等

为什么Key是无序的?

因为哈希存储是无需的底层数据结构的原因

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值