map基础操作
1. 字典类型(Map)
在学习任何的编程语言时,一般都会一种数据类型称为:字典(dict)或映射(map),以键值对为元素的数据集合。例如:
{
"age":"18",
"name":"武沛齐",
"email":"wupeiqi@live.com"
}
这种类型最大的特点就是查找速度非常快,因为他的底层存储是基于哈希表存储的(不同语言还会有一些差异)。
以取模+拉链法
来快速了解下哈希表存储原理,如下图
这种结构之所以快,是因为根据key可以直接找到数据存放的位置;而其他的数据类型是需要从前到后去逐一比对,相对来说比较耗时。
以上只是基本的存储模型,而各个编程语言中的字典都会在此基础上进行相应的修改和优化(后续会深入讲解Golang中的map实现机制)。
Map的特点:
- 键不能重复
- 键必须可哈希(目前我们已学的数据类型中,可哈希的有:int/bool/float/string/array)
- 无序
接下来关于map我会从两个维度来进行讲解:
- 常见使用
- 底层原理剖析(面试常问)
2. 声明&初始化
// userInfo := map[string]string{}
userInfo := map[string]string{"name":"武沛齐","age":"18"}
userInfo["name"] // 武沛齐
userInfo["age"] = "20"
userInfo["email"] = "wupeiqi@live.com"
// data := make(map[int]int, 10)
data := make(map[int]int)
data[100] = 998
data[200] = 999
data := make(map[string]int)
data["100"] = 998
data["200"] = 999
// 声明,nil
var row map[string]int
row = data
data := make(map[string]int)
data["100"] = 998
data["200"] = 999
// 声明,nil
value := new(map[string]int)
// value["k1"] = 123 # 报错
value = &data
注意:键不重复 & 键必须可哈希(int/bool/float/string/array)
v1 := make(map[[2]int]float32)
v1[[2]int{1,1}] = 1.6
v1[[2]int{1,2}] = 3.4
v2 := make(map[[2]int][3]string )
v2[[2]int{1,1}] = [3]string{"武沛齐","alex","老妖"}
3. 常用操作
长度和容量
data := map[string]string{"n1":"武沛齐","n2":"alex"}
value := len(data) // 2
// 根据参数值(10),计算出合适的容量。
// 一个map 中会包含很多桶,每个桶中可以存放8个键值对。
info := make(map[string]string, 10)
info["n1"] = "武沛齐"
info["n2"] = "alex"
v1 := len(info) // 2
// v2 := cap(info) // 报错
添加
data := map[string]string{"n1":"武沛齐","n2":"alex"}
data["n3"] = "eric"
修改
data := map[string]string{"n1":"武沛齐","n2":"alex"}
data["n1"] = "eric"
删除
data := map[string]string{"n1":"武沛齐","n2":"alex"}
delete(data,"n2")
查看
data := map[string]string{"n1":"武沛齐","n2":"alex"}
data["n1"]
data := map[string]string{"n1":"武沛齐","n2":"alex"}
for key,value := range data{
fmt.Println(key,value)
}
data := map[string]string{"n1":"武沛齐","n2":"alex"}
for key := range data{
fmt.Println(key)
}
data := map[string]string{"n1": "武沛齐", "n2": "alex"}
for _, value := range data {
fmt.Println(value)
}
嵌套
v1 := make(map[string]int)
v2 := make(map[string]string)
v3 := make(map[string]...)
v4 := make(map[string][2]int)
v5 := make(map[string][]int)
v6 := make(map[string]map[int]int)
v7 := make(map[string][2]map[string]string)
v7["n1"] = [2]map[string]string{ map[string]string{"name":"武沛齐","age":"18"},map[string]string{"name":"alex","age":"78"}}
v7["n2"] = [2]map[string]string{ map[string]string{"name":"eric","age":"18"},map[string]string{"name":"seven","age":"78"}}
// 伪代码
v7 = {
n1:[
{"name":"武沛齐","age":"18"},
{"name":"alex","age":"78"}
],
n2:[
{"name":"eric","age":"18"},
{"name":"seven","age":"78"}
]
}
前提:键不重复 & 键必须可哈希
v8 := make(map[int]int)
v9 := make(map[string]int)
v10 := make(map[float32]int)
v11 := make(map[bool]int)
v12 := make(map[ [2]int ]int)
v13 := make(map[ []int ]int) // 错误,不可哈希
v14 := make(map[ map[int]int ]int) // 错误,不可哈希
v15 := make(map[ [2][]int ]int) // 报错
v16 := make(map[ [2]map[string]string ]int) // 报错
变量赋值
v1 := map[string]string{"n1":"武沛齐","n2":"alex"}
v2 := v1
v1["n1"] = "wupeiqi"
ftm.Println(v1) // {"n1":"wupeiqi","n2":"alex"}
ftm.Println(v2) // {"n1":"wupeiqi","n2":"alex"}
特别提醒:无论是否存在扩容都指向同一个地址。