golang map的使用:
参考:由浅入深聊聊Golang的map_咖啡色的羊驼-CSDN博客_golang map
golang map的设计思想:
参考:【Golang】Map长啥样儿?_哔哩哔哩_bilibili
1.首先golang的map实际上就是一个hash表,首先按照key-value存储,对key进行哈希然后存到value中,如果value冲突了,就在相同位置新增一个链表,将新的value存储到链表中。
2.key的定位
根据key的的高8位对桶的数量进行哈希,然后分配到不同的捅中。
3.溢出桶
溢出桶就相当于value的链表,当原始的桶放满了,就直接放到溢出桶。
4.如何扩容
负载因子=存储的数量/桶的数量。
扩容的触发条件:
(1)当负载因子到了一个阈值,就开始翻倍扩容(新桶数量是旧桶2倍)
扩容的过程就是把分配一个容量足够大的新桶,把旧桶的内容转移到新桶中。转移的时候,会记录一个旧桶的首地址和旧桶迁移的进度(旧桶迁移完成的位置),一直到旧桶迁移完成就算扩容完成了。迁移的时间点:每次有map的读写操作时,就会完成一部分的迁移操作,这样可以避免每次迁移的时候的消耗(渐进式扩容)。
(2)当负载因子没超标,但是溢出桶达到阈值了,就开始等量扩容(新桶和旧桶数量一样多)。为啥要等量扩容呢?因为map里面的delete的时候其实没有真正的删除,只是置了一个标记位,等gc的时候才真正删除,所以等量扩容可以让内存排列更整齐。