map

MAP

非thread-safe

数据结构

          ┌─────────────┐                                                                                                                                                                                                           
          │    hmap     │                                                                                                                                                                                                           
          ├─────────────┴──────────────────┐           ┌───────────────┐                                        ┌─────────┐                               ┌─────────┐                                                               
          │           count int            │           │               │                     ┌─────────────────▶│  bmap   │                          ┌───▶│  bmap   │                                                               
          │                                │           │               ▼                     │                  ├─────────┴─────────────────────┐    │    ├─────────┴─────────────────────┐                                         
          ├────────────────────────────────┤           │    ────────┬─────┐                  │                  │   tophash [bucketCnt]uint8    │    │    │   tophash [bucketCnt]uint8    │                                         
          │          flags uint8           │           │       ▲    │  0  │                  │                  │                               │    │    │                               │                                         
          │                                │           │       │    │     │──────────────────┘                  ├──────────┬────────────────────┤    │    ├──────────┬────────────────────┤                                         
          ├────────────────────────────────┤           │       │    ├─────┤                                     │   keys   │                    │    │    │   keys   │                    │                                         
          │            B uint8             │           │       │    │  1  │                                     ├───┬───┬──┴┬───┬───┬───┬───┬───┤    │    ├───┬───┬──┴┬───┬───┬───┬───┬───┤                                         
          │                                │           │       │    │     │──────────────────┐                  │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │    │    │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │                                         
          ├────────────────────────────────┤           │       │    ├─────┤                  │                  ├───┴───┴──┬┴───┴───┴───┴───┴───┤    │    ├───┴───┴──┬┴───┴───┴───┴───┴───┤                                         
          │        noverflow uint16        │           │       │    │  2  │                  │                  │  values  │                    │    │    │  values  │                    │                                         
          │                                │           │       │    │     │                  │                  ├───┬───┬──┴┬───┬───┬───┬───┬───┤    │    ├───┬───┬──┴┬───┬───┬───┬───┬───┤                                         
          ├────────────────────────────────┤           │       │    ├─────┤                  │                  │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │    │    │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │                                         
          │          hash0 uint32          │           │       │    │  3  │                  │                  ├───┴───┴───┴───┴───┴───┴───┴───┤    │    ├───┴───┴───┴───┴───┴───┴───┴───┤                                         
          │                                │           │       │    │     │                  │                  │        overflow *bmap         │    │    │        overflow *bmap         │                                         
          ├────────────────────────────────┤           │       │    ├─────┤                  │                  │                               │────┘    │                               │                                         
          │     buckets unsafe.Pointer     │           │       │    │  4  │                  │                  ├─────────┬─────────────────────┘         └───────────────────────────────┘                                         
          │                                │───────────┘       │    │     │                  └─────────────────▶│  bmap   │                                                                                                         
          ├────────────────────────────────┤                        ├─────┤                                     ├─────────┴─────────────────────┐                                                                                   
          │   oldbuckets unsafe.Pointer    │                        │  5  │                                     │   tophash [bucketCnt]uint8    │                                                                                   
          │                                │                        │     │                                     │                               │                                                                                   
          ├────────────────────────────────┤         size = 2 ^ B   ├─────┤                                     ├──────────┬────────────────────┤                                                                                   
          │       nevacuate uintptr        │                        │  6  │                                     │   keys   │                    │                                                                                   
          │                                │                        │     │                                     ├───┬───┬──┴┬───┬───┬───┬───┬───┤                                                                                   
          ├────────────────────────────────┤                   │    ├─────┤                                     │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │                                                                                   
          │        extra *mapextra         │                   │    │  7  │                                     ├───┴───┴──┬┴───┴───┴───┴───┴───┤                                                                                   
       ┌──│                                │                   │    │     │                                     │  values  │                    │                                                                                   
       │  └────────────────────────────────┘                   │    └─────┘                                     ├───┬───┬──┴┬───┬───┬───┬───┬───┤                                                                                   
       │                                                       │      ....                                      │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │                                                                                   
       │                                                       │                                                ├───┴───┴───┴───┴───┴───┴───┴───┤                                                                                   
       │                                                       │    ┌─────┐                                     │        overflow *bmap         │                                                                                   
       │                                                       │    │ 61  │                                     │                               │                                                                                   
       │                                                       │    │     │                                     └───────────────────────────────┘                                                                                   
       ▼                                                       │    ├─────┤                                               ............                                                                                              
┌─────────────┐                                                │    │ 62  │                                     ┌─────────┐                               ┌─────────┐                              ┌─────────┐                      
│  mapextra   │                                                │    │     │────────────────────────────────────▶│  bmap   │                          ┌───▶│  bmap   │                         ┌───▶│  bmap   │                      
├─────────────┴──────────────┐                                 │    ├─────┤                                     ├─────────┴─────────────────────┐    │    ├─────────┴─────────────────────┐   │    ├─────────┴─────────────────────┐
│     overflow *[]*bmap      │                                 │    │ 63  │                                     │   tophash [bucketCnt]uint8    │    │    │   tophash [bucketCnt]uint8    │   │    │   tophash [bucketCnt]uint8    │
│                            │                                 ▼    │     │──────────────────┐                  │                               │    │    │                               │   │    │                               │
├────────────────────────────┤                              ────────┴─────┘                  │                  ├──────────┬────────────────────┤    │    ├──────────┬────────────────────┤   │    ├──────────┬────────────────────┤
│    oldoverflow *[]*bmap    │                                                               │                  │   keys   │                    │    │    │   keys   │                    │   │    │   keys   │                    │
│                            │                                                               │                  ├───┬───┬──┴┬───┬───┬───┬───┬───┤    │    ├───┬───┬──┴┬───┬───┬───┬───┬───┤   │    ├───┬───┬──┴┬───┬───┬───┬───┬───┤
├────────────────────────────┤                                                               │                  │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │    │    │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │   │    │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │
│     nextoverflow *bmap     │                                                               │                  ├───┴───┴──┬┴───┴───┴───┴───┴───┤    │    ├───┴───┴──┬┴───┴───┴───┴───┴───┤   │    ├───┴───┴──┬┴───┴───┴───┴───┴───┤
│                            │                                                               │                  │  values  │                    │    │    │  values  │                    │   │    │  values  │                    │
└────────────────────────────┘                                                               │                  ├───┬───┬──┴┬───┬───┬───┬───┬───┤    │    ├───┬───┬──┴┬───┬───┬───┬───┬───┤   │    ├───┬───┬──┴┬───┬───┬───┬───┬───┤
                                                                                             │                  │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │    │    │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │   │    │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │
                                                                                             │                  ├───┴───┴───┴───┴───┴───┴───┴───┤    │    ├───┴───┴───┴───┴───┴───┴───┴───┤   │    ├───┴───┴───┴───┴───┴───┴───┴───┤
                                                                                             │                  │        overflow *bmap         │    │    │        overflow *bmap         │   │    │        overflow *bmap         │
                                                                                             │                  │                               │────┘    │                               │───┘    │                               │
                                                                                             │                  ├─────────┬─────────────────────┘         └───────────────────────────────┘        └───────────────────────────────┘
                                                                                             └─────────────────▶│  bmap   │                                                                                                         
                                                                                                                ├─────────┴─────────────────────┐                                                                                   
                                                                                                                │   tophash [bucketCnt]uint8    │                                                                                   
                                                                                                                │                               │                                                                                   
                                                                                                                ├──────────┬────────────────────┤                                                                                   
                                                                                                                │   keys   │                    │                                                                                   
                                                                                                                ├───┬───┬──┴┬───┬───┬───┬───┬───┤                                                                                   
                                                                                                                │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │                                                                                   
                                                                                                                ├───┴───┴──┬┴───┴───┴───┴───┴───┤                                                                                   
                                                                                                                │  values  │                    │                                                                                   
                                                                                                                ├───┬───┬──┴┬───┬───┬───┬───┬───┤                                                                                   
                                                                                                                │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │                                                                                   
                                                                                                                ├───┴───┴───┴───┴───┴───┴───┴───┤                                                                                   
                                                                                                                │        overflow *bmap         │                                                                                   
                                                                                                                │                               │                                                                                   
                                                                                                                └───────────────────────────────┘                                                                                   
const (
    // 一个 bucket 最多能放的元素数
    bucketCntBits = 3
    bucketCnt     = 1 << bucketCntBits

    // load factor = 13/2
    loadFactorNum = 13
    loadFactorDen = 2

    // 超过这两个 size 的对应对象,会被转为指针
    maxKeySize   = 128
    maxValueSize = 128

    // data offset should be the size of the bmap struct, but needs to be
    // aligned correctly. For amd64p32 this means 64-bit alignment
    // even though pointers are 32 bit.
    dataOffset = unsafe.Offsetof(struct {
        b bmap
        v int64
    }{}.v)

    // tophash 除了放正常的高 8 位的 hash 值
    // 还会在空闲、迁移时存储一些特征的状态值
    // 所以合法的 tophash(指计算出来的那种),最小也应该是 4
    // 小于 4 的表示的都是我们自己定义的状态值
    empty          = 0 // cell is empty
    evacuatedEmpty = 1 // cell is empty, bucket is evacuated.
    evacuatedX     = 2 // key/value is valid.  Entry has been evacuated to first half of larger table.
    evacuatedY     = 3 // same as above, but evacuated to second half of larger table.
    minTopHash     = 4 // minimum tophash for a normal filled cell.

    // flags
    iterator     = 1 // there may be an iterator using buckets
    oldIterator  = 2 // there may be an iterator using oldbuckets
    hashWriting  = 4 // a goroutine is writing to the map
    sameSizeGrow = 8 // the current map growth is to a new map of the same size

    // sentinel bucket ID for iterator checks
    noCheck = 1<<(8*sys.PtrSize) - 1
)
//src/runtime/map.go
type hmap struct {
    // 元素个数,调用 len(map) 时,直接返回此值
	count     int
	flags     uint8
	// buckets 的对数 log_2
	B         uint8
	// overflow 的 bucket 近似数
	noverflow uint16
	// 计算 key 的哈希的时候会传入哈希函数
	hash0     uint32
    // 指向 buckets 数组,大小为 2^B
    // 如果元素个数为0,就为 nil
	buckets    unsafe.Pointer
	// 扩容的时候,buckets 长度会是 oldbuckets 的两倍
	oldbuckets unsafe.Pointer
	// 指示扩容进度,小于此地址的 buckets 迁移完成
	nevacuate  uintptr
	extra *mapextra // optional fields
}
type mapextra struct {
    // 如果 key 和 value 都不包含指针,并且可以被 inline(<=128 字节)
    // 使用 extra 来存储 overflow bucket,这样可以避免 GC 扫描整个 map
    // 然而 bmap.overflow 也是个指针。这时候我们只能把这些 overflow 的指针
    // 都放在 hmap.extra.overflow 和 hmap.extra.oldoverflow 中了
    // overflow 包含的是 hmap.buckets 的 overflow 的 bucket
    // oldoverflow 包含扩容时的 hmap.oldbuckets 的 overflow 的 bucket
    overflow    *[]*bmap
    oldoverflow *[]*bmap

    // 指向空闲的 overflow bucket 的指针
    nextOverflow *bmap
}
  • B:是 buckets 数组的长度的对数,也就是说 buckets 数组的长度就是 2^B。bucket 里面存储了 key 和 value;
  • buckets:是一个指针,最终它指向的是一个结构体:
type bmap struct {
	tophash [bucketCnt]uint8
}

但这只是表面(src/runtime/hashmap.go)的结构,编译期间会给它加料,动态地创建一个新的结构:

type bmap struct {
    topbits  [8]uint8//哈希值相同的键(准确的说是哈希值低位相同的键)存入当前bucket时会将哈希值的高位存储在该数组中,以方便后续匹配
    keys     [8]keytype
    values   [8]valuetype
    pad      uintptr
    overflow uintptr //指向的是下一个bucket,据此将所有冲突的键连接起来
}

  • bmap:就是常说的“桶”,桶里面会最多装 8 个 key,这些 key 之所以会落入同一个桶,是因为它们经过哈希计算后,哈希结果是“一类”的。在桶内,又会根据 key 计算出来的 hash 值的高 8 位来决定 key 到底落入桶内的哪个位置(一个桶内最多有8个位置)
    bmap 是存放 k-v 的地方:

    key 和 value 是各自放在一起的,并不是 key/value/key/value/... 这样的形式。源码里说明这样的好处是在某些情况下可以省略掉 padding 字段,节省内存空间。
    每个 bucket 设计成最多只能放 8 个 key-value 对,如果有第 9 个 key-value 落入当前的 bucket,那就需要再构建一个 bucket ,通过 overflow 指针连接起来。

创建

https://my.oschina.net/renhc/blog/2208417

ageMp := make(map[string]int)
// 指定 map 长度
ageMp := make(map[string]int, 8)

// ageMp 为 nil,不能向其添加元素,会直接panic
var ageMp map[string]int

作参数

makemap 和 makeslice 的区别,带来一个不同点:当 map 和 slice 作为函数参数时,在函数参数内部对 map 的操作会影响 map 自身;而对 slice 却不会.
主要原因:一个是指针(hmap),一个是结构体(slice)。Go 语言中的函数传参都是值传递,在函数内部,参数会被 copy 到本地。hmap指针 copy 完之后,仍然指向同一个 map,因此函数内部对 map 的操作会影响实参。而 slice 被 copy 后,会成为一个新的 slice,对它进行的操作不会影响到实参

哈希函数

哈希函数的选择。在程序启动时,会检测 cpu 是否支持 aes,如果支持,则使用 aes hash,否则使用 memhash。这是在函数 alginit() 中完成,位于路径:src/runtime/alg.go

hash 函数,有加密型和非加密型。
加密型的一般用于加密数据、数字摘要等,典型代表就是 md5、sha1、sha256、aes256 这种;
非加密型的一般就是查找。在 map 的应用场景中,用的是查找。
选择 hash 函数主要考察的是两点:性能、碰撞概率。

key定位

https://github.com/cch123/golang-notes/blob/master/map.md
https://my.oschina.net/renhc/blog/2208417
key 经过哈希计算后得到哈希值,共 64 个 bit 位,计算它到底要落在哪个桶时,只会用到最后 B 个 bit 位。hmap.B,如果 B = 5,那么桶的数量,也就是 buckets 数组的长度是 2^5 = 32

假定 B = 5,所以 bucket 总数就是 2^5 = 32。首先计算出待查找 key 的哈希,使用低 5 位 00110,找到对应的 6 号 bucket,使用高 8 位 10010111,对应十进制 151,在 6 号 bucket 中寻找 tophash 值(HOB hash)为 151 的 key,找到了 2 号槽位,这样整个查找过程就结束了。

如果在 bucket 中没找到,并且 overflow 不为空,还要继续去 overflow bucket 中寻找,直到找到或是所有的 key 槽位都找遍了,包括所有的 overflow bucket

map 的两种 get 操作

Go 语言中读取 map 有两种语法:带 comma 和 不带 comma。当要查询的 key 不在 map 里,带 comma 的用法会返回一个 bool 型变量提示 key 是否在 map 中;而不带 comma 的语句则会返回一个 value 类型的零值。如果 value 是 int 型就会返回 0,如果 value 是 string 类型,就会返回空字符串.

package main

import "fmt"

func main() {
	ageMap := make(map[string]int)
	ageMap["qcrao"] = 18

    // 不带 comma 用法
	age1 := ageMap["stefno"]
	fmt.Println(age1)

    // 带 comma 用法
	age2, ok := ageMap["stefno"]
	fmt.Println(age2, ok)
0
0 false

两种语法对应到底层函数

// src/runtime/hashmap.go
func mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer
func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool)

根据 key 的不同类型
src/runtime/hashmap_fast.go

key类型 查找
uint32 mapaccess1_fast32(t *maptype, h *hmap, key uint32) unsafe.Pointer
uint32 mapaccess2_fast32(t *maptype, h *hmap, key uint32) (unsafe.Pointer, bool)
uint64 mapaccess1_fast64(t *maptype, h *hmap, key uint64) unsafe.Pointer
uin64 mapaccess2_fast64(t *maptype, h *hmap, key uint64) (unsafe.Pointer, bool)
string mapaccess1_faststr(t *maptype, h *hmap, ky string) unsafe.Pointer
string mapaccess2_faststr(t *maptype, h *hmap, ky string) (unsafe.Pointer, bool)

哈希冲突(碰撞问题)

不同的key,哈希结果在同一个bucket中,解决有两种方法。链表法,开放地址法;

链表法

链表法将一个 bucket 实现成一个链表,落在同一个 bucket 中的 key 都会插入这个链表

开放地址法

碰撞发生后,通过一定的规律,在数组的后面挑选“空位”,用来放置新的 key。

扩容

哈希冲突会影响哈希表的读写效率,选择散列均匀的哈希函数可以减少哈希冲突的发生,适时对哈希表进行扩容也是保障读写效率的有效手段

扩容前提条件

为了保证访问效率,当新元素将要添加进map时,都会检查是否需要扩容,扩容实际上是以空间换时间的手段。
触发扩容的条件有二个:

  1. 负载因子 > 6.5时,也即平均每个bucket存储的键值对达到6.5个。
    负载因子:hmap.count(键值对总数)/hmap.buckets(bucket总数)
  2. overflow数量 > 2^15时,也即overflow数量超过32768时。

渐进式扩容

增量扩容

等量扩容

缩容

GO的map是不会缩容的,除非你把整个map删掉

查找过程

  1. 跟据key值算出哈希值
    2.取哈希值低位与hmpa.B取模确定bucket位置
    3.取哈希值高位在tophash数组中查询
    4.如果tophash[i]中存储值也哈希值相等,则去找到该bucket中的key值进行比较
    5.当前bucket没有找到,则继续从下个overflow的bucket中查找。
    6.如果当前处于搬迁过程,则优先从oldbuckets查找
    注:如果查找不到,也不会返回空值,而是返回相应类型的0值。

插入过程

1.跟据key值算出哈希值
2.取哈希值低位与hmap.B取模确定bucket位置
3.查找该key是否已经存在,如果存在则直接更新值
4.如果没找到key,将key插入

哈希查表

返回的 key 序列,哈希查找表则是乱序的

搜索树

自平衡搜索树

返回的 key 序列,一般会按照从小到大的顺序

AVL树
红黑树

实例1

func mapAddr() {
	var mp = map[int]int{1: 2, 2: 3, 3: 4}
	fmt.Printf("初始化map地址:%p\n", &mp)

	fmt.Println("循环取值")

	// Tip  注意range中的k是不能保证顺序的
	for k, v := range mp {
		// Tip k,v 是为了遍历、另外开辟内存的一对变量,不是map中key/value保存的地址
		fmt.Printf("k地址:%p,v地址:%p\n", &k, &v)
		// Tip 修改k/v后,map中所对应的k/v不会生效
		k++
		v++
		// Tip 如果在这里加上一个delete操作,在k=1且++后,删除的是k=2的元素,在次遍历就是k=3的元素
		// map的delete是安全的,不会存在race等竞争问题,这里用到的k,v是值复制,删除是针对hmap的操作
		delete(mp, k)
                // 编译错误,value不可寻址,因为这个在内部是频繁变化的
		// fmt.Printf("&mp[k]:%p\n", &mp[k])
	}
	fmt.Println("输出mp:", mp)
}
1.输出结果,循环k:1,2,3
初始化map地址:0xc00000e028
循环取值
k地址:0xc0000160b0,v地址:0xc0000160b8
k地址:0xc0000160b0,v地址:0xc0000160b8
输出mp: map[1:2 3:4]

2.输出结果,循环k:2,1
初始化map地址:0xc00000e028
循环取值
k地址:0xc0000160b0,v地址:0xc0000160b8
k地址:0xc0000160b0,v地址:0xc0000160b8
输出mp: map[1:2]

说明range中的k不是顺序获取的

实例2

func mapModify() {
	//Tip 初始化map时指定size,会减少hmap扩容时带来的内存重新分配,减少性能损失
	// var mp=make(map[int]int,1000)
	var mp = make(map[int]int)
	mp[1] = 2
	mp[2] = 3
	mp[3] = 4
	var count int
	fmt.Printf("循环前map长度:%d\n", len(mp))
	for k, v := range mp {
		count++
		// Tip 在range的过程中,如果不断扩容,何时退出是不确定的
		mp[k+1] = v + 1
	}
	fmt.Printf("循环后map长度:%d\n", len(mp))
	fmt.Printf("循环次数:%d\n", count)
}
1. 输出结果
循环前map长度:3
循环后map长度:9
循环次数:8
2. 输出结果
循环前map长度:3
循环后map长度:5
循环次数:4
3. 输出结果
循环前map长度:3
循环后map长度:4
循环次数:3

实例3

func mapReplace() {
	o := make(map[string]string) //原map
	r := make(map[string]string) //替换map

	o["a"] = "x"
	o["b"] = "y"

	r["a"] = "1"
	r["b"] = "2"

	fmt.Printf("输出o:%v,长度:%d\n", o, len(o))
	// Tip 因为o的k-v是在不断增加的,所以遍历何时结束是不确定的
	// 此是k可能为"1"或"2",对应的r[k]是不存在的,返回定义时类型的默认值,空字符串""
	for k, v := range o {
		o[r[k]] = v
	}
	// Tip 为什么每次运行结果会不一致?
	// 1. 遍历在hmap中是通过buckets进行的
	// 2. 每次运行时,分配的bucket是有随机的
	// 3. hash0是个随机值,确认其对分配
	fmt.Printf("替换输出o:%v,长度:%d\n", o, len(o))
	delete(o, "a")
	delete(o, "b")
	fmt.Printf("删除k:a,b输出o:%v,长度:%d\n", o, len(o))
}
1. 结果输出
输出o:map[a:x b:y],长度:2
替换输出o:map[:y 1:x 2:y a:x b:y],长度:5 //:y  k可能为"1"或"2",对应的r[k]是不存在的,返回定义时类型的默认值,空字符串""
删除k:a,b输出o:map[:y 1:x 2:y],长度:3
2. 结果输出
输出o:map[a:x b:y],长度:2
替换输出o:map[1:x 2:y a:x b:y],长度:4
删除k:a,b输出o:map[1:x 2:y],长度:2
3. 结果输出
输出o:map[a:x b:y],长度:2
替换输出o:map[:x 1:x 2:y a:x b:y],长度:5
删除k:a,b输出o:map[:x 1:x 2:y],长度:3

实例4-实现set

  • struct{}
func mapSet() {
	// 空struct是不占用空间的
	var mp = make(map[string]struct{})
	fmt.Println(mp)
	var s1 struct{}
	fmt.Println(unsafe.Sizeof(s1)) // prints 0
	type S struct {
		a uint16
		b uint32
	}
	var s S
	fmt.Println(unsafe.Sizeof(s)) // prints 8, not 6

	a := struct{}{}
	b := struct{}{}
	fmt.Println(a == b)            // true
	fmt.Printf("%p, %p\n", &a, &b) // 0x55a988, 0x55a988
}
  • Set实现
//map key放置数据
type Set struct {
	m map[interface{}]struct{}
}

//获取Set
func GetSet() *Set {
	return &Set{
		m: make(map[interface{}]struct{}),
	}
}

//返回key的数组
func (s *Set) GetArray() *[]interface{} {

	l := len(s.m)
	array := make([]interface{}, l)
	sum := 0
	for k, _ := range s.m {
		array[sum] = k
		sum++
	}
	return &array
}

//增加元素,判断是否存在
func (s *Set) Add(i interface{}) bool {
	if _, ok := s.m[i]; ok {
		return false
	} else {
		s.m[i] = struct{}{}
		return true
	}
}

//删除元素
func (s *Set) Remove(i interface{}) {
	delete(s.m, i)
}

//清除元素
func (s *Set) Clear() {
	s.m = make(map[interface{}]struct{})
}

//获取长度
func (s *Set) GetLen() int {
	return len(s.m)
}
func main(){
       s := GetSet()
	b := s.Add(1)
	s.Add(2)
	s.Add(3)
	s.Add("5")
	s.Add(1.1)
	fmt.Println(b)
	fmt.Println("s len:", s.GetLen())
	a := s.GetArray()
	fmt.Println("key arr:", *a)
}
结果输出
true
s len: 5
key arr: [5 1.1 1 2 3]

实例5-嵌套map

func nestMap() {
	// 只会初始化第一层map
	var mp = make(map[string]map[string]string)
	fmt.Println("第一层初始化:", mp)
	//使第二层时初始化
	mp["test"] = make(map[string]string)
	fmt.Println("第二层初始化:", mp)
}
结果输出
第一层初始化: map[]
第二层初始化: map[test:map[]]

map示例总结:

  1. map读取某个值时-返回结果可以为value,bool或者value.注意后者,在key不存在时,会返回value对应类型的默认值(channel相同)
  2. map的range方法需要注意-key,value或者key.注意后者,可以和slice的使用结合起来
  3. map的range操作-key,value都是值复制
  4. map如何保证按key的某个顺序遍历?
    分两次遍历,第一次取出所有key并排序;第二次按排序后的key去遍历(可将map和slice封装到一个结构体中)
  5. map的使用上,需要注意?
    遍历时,尽量只修改或删除当前key,操作非当前key会带来不可预知的结果
posted @ 2021-10-15 15:47  wangzhilei  阅读(87)  评论(0)    收藏  举报