map:
- map是key-value的数据结构,类似于Java的集合,又称为字典,像新华字典就是key:value类型展示的
- map是无序的,其中key是不允许重复的,key不存在相当于添加,存在相当于修改
- map的key必须可以进行支持相等运算,比如slice、map、function不可以,因为不能用== !=判断,引用类型不能作为key
- map必须先make才能使用,否则是一个空map且无法向该map添加数据
- map的key通常使用int、string,value
声明map:
格式1:
var map名称 map[key的类型]value的类型
格式2:
map名称 := map[key的类型]value的类型{}
格式3:
map名称 := make(map[key的类型]value的类型,size)
// map的大小是可以省略不写的,不写的时候会按照数据的大小自动分配
map声明后是不会分配内存的,比如数组创建完不管用不用内存都会开辟一块空间,但是map必须使用make关键字后才分配内存及使用,否则是一个空map且无法向该map添加数据
func main() {var m1 map[int]stringvar m2 = map[int]string{}m3 := make(map[int]string)fmt.Println("添加数据前m1:", m1)fmt.Println("添加数据前m2:", m2)fmt.Println("添加数据前m3:", m3)//m1[0] = "李白" // panic: assignment to entry in nil map//m2[0] = "韩信" // panic: assignment to entry in nil mapm3[0] = "露娜"fmt.Println("添加数据后m3:", m3)
}
输出:
添加数据前m1: map[]
添加数据前m2: map[]
添加数据前m3: map[]
添加数据后m3: map[0:露娜]
map的初始化:
格式1:
var map名称 map[key的类型]value的类型 = map[key的类型]value的类型{key:value,key:value}
格式2:
map名称 := map[key的类型]value的类型{key:value,key:value}
格式3:
map名称 := make(map[key的类型]value的类型)
map名称 [key] = value
如果key不存在就是添加,否则就是修改
func main() {// 方式1var m1 map[string]stringm1 = make(map[string]string)m1["打野"] = "露娜"m1["中路"] = "不知火舞"m1["中路"] = "干将莫邪"fmt.Println("m1:", m1)// 方式2m2 := map[string]string{"打野": "露娜","中路": "不知火舞","射手": "马可波罗",}fmt.Println("m2:", m2)// 方式3m3 := make(map[string]string)m3["打野"] = "露娜"m3["中路"] = "不知火舞"m3["射手"] = "马可波罗"fmt.Println("m3:", m3)// 方式4m4 := map[string]string{"打野": "露娜", "中路": "不知火舞", "射手": "马可波罗"}m4["新增"] = "我新增了吗"fmt.Println("m4:", m4)// 注意:因为key不能重复,如果都为空,也是相当于重复了m5 := map[string]string{"": "", // 报错:映射文字中的键 重复"": "",}fmt.Println("m5", m5)
}
输出:
m: map[中路:不知火舞 射手:马可波罗 打野:露娜 新增:我新增了吗]
m1: map[中路:干将莫邪 打野:露娜]
m2: map[中路:不知火舞 射手:马可波罗 打野:露娜]
m3: map[中路:不知火舞 射手:马可波罗 打野:露娜]
map的value可以是另一个map
func main() {// key是int// value是一个map,这个map是的key和value都是stringm := make(map[int]map[string]string)// 因为value也是一个map所以需要再make一下才可以赋值m[0] = make(map[string]string)m[0]["打野"] = "韩信"m[1] = make(map[string]string)m[1]["打野"] = "韩信"fmt.Println(m)
}
输出:
map[0:map[打野:韩信] 1:map[打野:韩信]]
map键值操作:
格式 | 作用 |
---|---|
map名称[键] | 通过key获取值 |
value,ok := map[key] | 判断key是否存在 |
delete(map名称,键) | 通过key删除value,即使key不存在也不会报错 |
演示:
func main() {m := map[string]string{"打野": "露娜", "中路": "不知火舞", "射手": "马可波罗"}// 通过key获取valuefmt.Println(m["中路"])// 直接删除keyfmt.Println("删除前:", m)delete(m, "打野")delete(m, "打野2") // 这里删除一个不存在key,是不会报错的fmt.Println("删除后:", m)// 判断key是否存在,key存在ok返回truevalue, key := m["打野"]if key {fmt.Println(value)} else {fmt.Println("key不存在")}
}
输出:
不知火舞
删除前: map[中路:不知火舞 射手:马可波罗 打野:露娜]
删除后: map[中路:不知火舞 射手:马可波罗]
key不存在
查找:
func main() {m := map[string]string{"打野": "露娜", "中路": "不知火舞", "射手": "马可波罗"}value, ok := m["打野"]fmt.Println("直接输出:", value, ok)// 判断后再输出if ok {fmt.Println("key", value, "存在")} else {fmt.Println("key", value, "不存在")}
}
输出:
直接输出: 露娜 true
key 露娜 存在
统计map键值对个数
func main() {m := map[string]string{"打野": "露娜", "中路": "不知火舞", "射手": "马可波罗"}fmt.Println(len(m))
}
Map的遍历
func main() {m := map[string]string{"打野": "露娜", "中路": "不知火舞", "射手": "马可波罗"}for key, value := range m {fmt.Println(key, value)}
}func main() {// value是一个mapm := make(map[int]map[string]string)m[0] = make(map[string]string)m[0]["打野"] = "韩信"for key, value := range m {fmt.Print("key:", key, " ")for v1, v2 := range value {fmt.Println(v1, v2)}}
}
输出:
key:0 打野 韩信
删除map
直接make一个新的map,让原来的成为垃圾,被GC回收
func main() {m := map[string]string{"打野": "露娜", "中路": "不知火舞", "射手": "马可波罗"}fmt.Println("重新make前:", m)m = make(map[string]string)fmt.Println("重新make后:", m)
}
输出:
重新make前: map[中路:不知火舞 射手:马可波罗 打野:露娜]
重新make后: map[]
或者使用遍历一个一个的删
func main() {m2 := map[string]string{"打野": "露娜", "中路": "不知火舞", "射手": "马可波罗"}fmt.Println("删除前:", m2)for k, _ := range m2 {delete(m2, k)}fmt.Println("删除后:", m2)
}
输出:
删除前: map[中路:不知火舞 射手:马可波罗 打野:露娜]
删除后: map[]
map作为函数参数:
在函数中修改map的值,会影响到原来的map
func main() {m := map[string]string{"打野": "露娜", "中路": "不知火舞", "射手": "马可波罗"}mapDemo(m)fmt.Println("修改后main中打印:", m)
}func mapDemo(m map[string]string) {fmt.Println("修改前:", m)delete(m, "打野")fmt.Println("修改后mapDemo中打印:", m)
}
输出:
修改前: map[中路:不知火舞 射手:马可波罗 打野:露娜]
修改后mapDemo中打印: map[中路:不知火舞 射手:马可波罗]
修改后main中打印: map[中路:不知火舞 射手:马可波罗]
map切片:
如果把map作为切片的数据类型,那么map的个数就可以动态的变化了
func main() {// 声明并初始化切片slice := make([]map[string]string, 2)// 添加数据slice[0] = make(map[string]string)slice[0]["name"] = "韩信"slice[0]["age"] = "99"slice[1] = make(map[string]string)slice[1]["name"] = "露娜"slice[1]["age"] = "19"fmt.Println(slice)// 可以继续往里面添加数据// 先创建一个map,再把map加到切片里newMap := map[string]string{"name": "猴子", "age": "23"}slice = append(slice, newMap)fmt.Println(slice)
}
输出:
[map[age:99 name:韩信] map[age:19 name:露娜]]
[map[age:99 name:韩信] map[age:19 name:露娜] map[age:23 name:猴子]]
切片是有序的,可以把map的key放在切片然后通过切片取value完成排序,但还是比较麻烦
func main() {TestMap := make(map[int]string)TestMap[0] = "韩信"TestMap[5] = "宫本"TestMap[3] = "猴子"TestMap[2] = "露娜"TestMap[6] = "火舞"TestMap[4] = "干将"// 现在输出就是无序的fmt.Println("排序前:", TestMap)// 可以把map添加到切片中,切片就会按照key排序var keys []intfor k, _ := range TestMap {keys = append(keys, k)}// sort.Ints、sort.Strings等内置函数可以对切片排序sort.Ints(keys)fmt.Println("排序后:")for _, k := range keys {fmt.Print(k, TestMap[k], "\t")}
}
输出:
排序前: map[0:韩信 2:露娜 3:猴子 4:干将 5:宫本 6:火舞]
排序后:
0韩信 2露娜 3猴子 4干将 5宫本 6火舞
将结构体作为value:
type Student struct {name stringage int
}func main() {stu := make(map[string]Student)stu1 := Student{"韩信", 18}stu2 := Student{"李白", 78}stu["001"] = stu1stu["002"] = stu2fmt.Println(stu)
}
输出:
map[001:{韩信 18} 002:{李白 78}]
统计字母出现的次数:
定义map,键盘录入的字母作为map的key,统计的次数作为map的value,循环遍历
func main() {fmt.Println("请输入要统计的字母:")// 定义统计次数的变量var str stringfmt.Scan(&str)m := make(map[byte]int)for i := 0; i < len(str); i++ {// 定义变量s作为map的keys := str[i]// 把S作为key,结果作为value,key如果重复,相当于修改m[s] += 1}fmt.Println("统计的字符次数为:")// 遍历for key, value := range m {fmt.Printf("%c:%d\n", key, value)}
}
输出:
请输入要统计的字母:
itzhuzhu
统计的字符次数为:
i:1
t:1
z:2
h:2
u:2