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
注意:nil map不能直接使用,不能向nil map中添加键值对
// 初始化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
}
// map[string][]int{"熊大":[]int{1, 2, 0, 3, 0}}
for k,v := range sliceMap{
fmt.Println(k, v) // 熊大 [1 2 0 3 0]
}
}