Go语言 - map
Go语言中提供的映射关系容器为map
,其内部使用散列表(hash)
实现。
map是一种无序的基于key-value
的数据结构,Go语言中的map是引用类型,必须初始化才能使用。
map内的键值对是无序的
map定义
Go语言中 map
的定义语法如下:
map[KeyType]ValueType
- KeyType:表示键的类型。
- ValueType:表示键对应的值的类型。
map类型的变量默认初始值为nil,需要使用make()函数来分配内存初始化。语法为:
make(map[KeyType]ValueType, [cap])
map初始化
-
方式一 :先声明再初始化
package main import "fmt" func main() { // 声明map var m map[string]int fmt.Println(m == nil) // true 引用类型只声明不初始化那么它就等于nil // 初始化map m = make(map[string]int, 5) // 为m申请内存,m的容量是5 fmt.Println(m == nil) // false }
-
方式二 : 声明同时初始化
package main import "fmt" func main() { // 声明的同时初始化map m1 := map[int]bool{ 1:true, 2:false, } fmt.Println(m1) // map[1:true 2:false] }
其中cap表示map的容量,该参数虽然不是必须的,但是我们应该在初始化map的时候就为其指定一个合适的容量。
map使用
基本使用 添加键值对
map中的数据都是成对出现的
func main() { m := make(map[string]int, 5) // map中添加键值对 m["熊大"] = 100 m["熊二"] = 200 fmt.Println(m) // map[熊二:200 熊大:100] fmt.Printf("m:%#v \n", m) // m:map[string]int{"熊二":200, "熊大":100} fmt.Printf("m:%T \n", m) // m:map[string]int }
判断某个键是否存在
Go语言中有个判断map中键是否存在的特殊写法,格式如下:
value, ok := map[key] // key存在map中, value就是key的值, ok为true // key不存在map中,value就是map值的默认值, ok为false
eg:
func main() { course := map[string]int{ "熊大": 100, "熊二": 90, } value, ok :=course["光头强"] if ok { fmt.Println("光头强存在course中", value, ok) }else{ fmt.Println("光头强不在course中", ok) // 光头强不在course中 0 false } }
map的遍历
Go语言中使用for range
遍历map。
-
遍历map中的键值对
func main() { course := map[string]int{ "熊大": 100, "熊二": 90, } for k, v := range course{ fmt.Printf("键:%s, 值:%d \n", k, v) } }
-
遍历map中的key
func main() { course := map[string]int{ "熊大": 100, "熊二": 90, } for k := range course{ fmt.Println(k) } }
-
遍历map中的value
func main() { course := map[string]int{ "熊大": 100, "熊二": 90, } for _, v := range course{ fmt.Println(v) } }
delete()函数删除键值对
使用delete()
内建函数从map中删除一组键值对,delete()
函数的格式如下:
delete(map, key)
- map:表示要删除键值对的map
- key:表示要删除的键值对的键
func main() { course := map[string]int{ "熊大": 100, "熊二": 90, } delete(course, "熊大") // delete(course, "光头强") fmt.Println(course) // map[熊二:90] }
注意: 当要删除的key不在map中时,map不做任何改变
按照指定顺序遍历map
package main import ( "math/rand" // 导入 rand "sort" // 导入 sort "fmt" ) func main() { // 按照某个固定顺序遍历map course := make(map[string]int, 10) // 循环添加10个键值对 for i :=0 ; i < 10; i++{ key := fmt.Sprintf("stu%02d", i) value := rand.Intn(10) // 随机0-9之间的整数 course[key] = value } for k, v := range course{ fmt.Println(k, v) } // 按照key从小到大的顺序遍历course // 1.先取出所有的key存放到切片中 keys := make([]string, 0 , 30) // 长度0, 容量30 for k := range course{ keys = append(keys, k) // 将遍历出来的k追加到keys中 } // 2. 对keys做排序 sort.Strings(keys) // keys中的数据类型是string,此时的keys是一个有序切片 // 3. 按照排序后的keys对course排序 for _, key := range keys{ fmt.Println(key, course[key]) } }
元素为map类型的切片
func main() { // 元素为map类型的切片 var mapSlice = make([]map[string]int, 3, 3) // 只是完成了切片的初始化 fmt.Println(mapSlice) // map[] map[] map[]] fmt.Println(mapSlice[0] == nil) // true // 需要完成内部map的初始化 mapSlice[0] = make(map[string]int, 8) mapSlice[0]["熊大"] = 10 fmt.Println(mapSlice) // [map[熊大:10] map[] map[]] }
值为切片类型的map
func main() { // 值为slice的map var sliceMap = make(map[string][]int, 8) // 只是完成了map的初始化 v, ok := sliceMap["熊大"] if ok{ fmt.Println(v) }else{ // 当sliceMap中没有熊大这个key时 sliceMap["熊大"] = make([]int, 5) // 完成对slice的初始化 sliceMap["熊大"][0] = 1 sliceMap["熊大"][1] = 2 sliceMap["熊大"][3] = 3 } fmt.Printf("%#v \n", sliceMap) // map[string][]int{"熊大":[]int{1, 2, 0, 3, 0}} for k,v := range sliceMap{ fmt.Println(k, v) // 熊大 [1 2 0 3 0] } }
通过map实现set
func main() { //集合 //可以放值,如果重复了,放不进去 //可以获取长度 //判断一个值是否在集合内 //把集合内所有元素打印出来 var m map[string]bool=make(map[string]bool) m["lqz"]=true m["egon"]=true m["lqz"]=true fmt.Println(len(m)) //"aa"是否在集合内 if m["aa"]{ fmt.Println("在里面") }else { fmt.Println("不再") } for k,_:=range m{ fmt.Println(k) } }