集合 Map
1.1 什么是Map
map是go语言内置类型,如果有编程基础的人,相信可以很快理解map究竟是什么,它将value与key关联起来,可以用key检索。
Map是一种无序键值对的集合,key类似索引,指向数据的value。
Map基于hash实现,所以这也是它无序的原因。
Map是引用类型。
1.2 关于map的几个知识点
使用Map需要注意以下几点:
- map无序,每次打印出来的map都会不一样。
- map长度不固定,和slice一样,也是引用类型
- 内置的len函数适用于map,返回map拥有key的数量。
- map的key是所有可以用== 或者!=比较的类型,如布尔、整数、浮点、字符串等。所以数组、切片不能作为key
- value是可以作为任意类型的,通过空接口,我们可以存储任意值,但是使用这种类型作为值时需要先做一次类型断言。
- map 传递给函数的代价很小:在 32 位机器上占 4 个字节,64 位机器上占 8 个字节,无论实际上存储了多少数据。通过 key 在 map 中寻找值是很快的,比线性查找快得多,但是仍然比从数组和切片的索引中直接读取要慢 100 倍;所以如果你很在乎性能的话还是建议用切片来解决问题
- map也可以用函数作为自己的值,这样可以用来做分支结构:key用来选择要执行的函数。
- 不要使用new,永远用make来构造map。如果使用new分配一个对象,你会获得一个空引用指针。
1.3 map的使用
先声明再make
var m map[string]string m = make(map[string]string,10)
声明的同时make
var m = make(map[string]string,10)
声明并直接赋值
var m map[string]string = map[string]string{"id": "01"}
来看一段代码:
var m map[string]string //定义一个map
m = make(map[string]string)
m2 := make(map[string]string)//简短写法
m["a"] = "apple" //放入key和value
m["b"] = "banana"
value, ok := m["a"] //ok是看当前key是否存在返回布尔,value返回对应key的值
if ok {
fmt.Printf("exist key, value is %s \n", value)
} else {
fmt.Println("not exist")
}
value2, ok := m2["a"]
if ok {
fmt.Printf("exist key, value is %s \n", value2)
} else {
fmt.Println("not exist")
}
结果如下:
exist key, value is apple not exist
not exist
1.4 遍历map
var m map[string]string
m = make(map[string]string)
m["a"] = "apple"
m["b"] = "banana"
for key,value := range dict{ //取map中的值
fmt.Println(key,"**********",value)
}
运行结果:
b =====> banana
a =====> apple
1.5 删除map元素
var m map[string]string
m = make(map[string]string)
m["a"] = "apple"
m["b"] = "banana"
delete(m, "a") // 删除m里的key:a
for key,value := range dict{ //取map中的值
fmt.Println(key,"**********",value)
}
运行结果:
b =====> banana
1.6 map与slice的使用
定义三个map,然后装进一个切片中,遍历切片。
m1 := map[string]string{
"name": "zhangsan",
"id": "01"}
m2 := map[string]string{
"name": "lisi",
"id": "02"}
m3 := map[string]string{
"name": "wangwu",
"id": "03"}
slice := make([]map[string]string, 0, 3)
slice = append(slice, m1)
slice = append(slice, m2)
slice = append(slice, m3)
for _, val := range slice {
fmt.Printf("name : %s, id : %s \n", val["name"], val["id"])
}
运行结果:
name : zhangsan, id : 01
name : lisi, id : 02
name : wangwu, id : 03
1.7 关于map是引用类型
如果现在有一个map 叫m3, 然后我们再定义一个map m4, 我们让m4 = m3, 如果我们改掉m3里key的value的话,那m4会保持不变还是跟着m3一样改变里面的value呢?
很明显,会跟着m3一样改变。
m3 := map[string]string{
"name": "wangwu",
"id": "03"}
m4 := m3
fmt.Println(m4) //第一次打印里面的内容
m3["name"] = "zhaoliu"
fmt.Println(m4) //第二次打印里面的内容
结果如下:
map[id:03 name:wangwu]
map[id:03 name:zhaoliu]
1.8 map的排序
基本介绍
- golang中没有一个专门的方法针对map的key进行排序
- golang中map默认无序,也不是按照添加的顺序存放的,你每次遍历,得到的输出可能不一样.
- golang中map的排序,是先将key进行排序,然后根据key值遍历输出即可
具体实现:TBD.
1.9 其他
map容量达到最大后, 再增加元素会自动扩容, 也就是说map会动态增长。