9 map Go 语言中提供的映射关系容器为 map ,其内部使用 散列表(hash) 实现。它是一种无序的基于 key-value 的数据结构。
Go 语言中的 map 是引用类型,必须初始化之后才能使用。
9.1 map 定义 Go 语言中 map 的定义语法为:map[keyType]valueType,其中:
keyType 表示键的类型
valueType 表示值的类型
map 类型变量默认初始值为 nil (引用类型的默认初始值都为 nil), 需要使用 make() 函数来分配内存,语法格式为:
1 make (map [keyType]valueType , cap )
上述格式中,cap 表示 map 的容量,不是必须的,map 可以动态扩容。但我们通常会在初始化的时候就指定一个合适的容量,因为这样会比动态扩容的执行效率高。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package mainimport "fmt" func main () { var b map [string ]int fmt.Println(nil == b) b = make (map [string ]int , 10 ) b["aa" ] = 100 b["bb" ] = 100 fmt.Println(b) }
9.2 map 的基本使用 9.2.1 增值和取值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package mainimport "fmt" func main () { var b map [string ]int fmt.Println(nil == b) b = make (map [string ]int , 10 ) b["aa" ] = 100 b["bb" ] = 100 fmt.Println(b["aa" ]) v, ok := b["cc" ] if !ok { fmt.Println("b 中不存在键 cc" ) } else { fmt.Println("cc对应的值为:" , v) } }
9.2.1 删除某个键值对 删除时使用内置函数 delete, 该函数的定义如下:
1 func delete (m map [Type]Type1, key Type)
如果被删除的键存在,直接删除,不存在,则不执行任何操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package mainimport ( "fmt" ) func main () { scoreMap := make (map [string ]int , 10 ) scoreMap["张三" ] = 93 scoreMap["李四" ] = 94 scoreMap["王五" ] = 95 delete (scoreMap, "张三" ) }
9.3 map 的遍历 9.3.1 for-range 遍历 1 2 3 4 5 6 7 8 9 10 11 12 13 14 package mainimport "fmt" func main () { scoreMap := make (map [string ]int , 10 ) scoreMap["张三" ] = 93 scoreMap["李四" ] = 94 scoreMap["王五" ] = 95 for k, v := range scoreMap { fmt.Println(k, v) } }
9.3.2 只遍历 key 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package mainimport ( "fmt" ) func main () { scoreMap := make (map [string ]int , 10 ) scoreMap["张三" ] = 93 scoreMap["李四" ] = 94 scoreMap["王五" ] = 95 for k := range scoreMap { fmt.Println(k, scoreMap[k]) } }
9.3.3 只遍历 value 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package mainimport ( "fmt" ) func main () { scoreMap := make (map [string ]int , 10 ) scoreMap["张三" ] = 93 scoreMap["李四" ] = 94 scoreMap["王五" ] = 95 for _, v := range scoreMap { fmt.Println(v) } }
9.3.4 按照指定顺序遍历 Go 语言中没有 map 专用的排序,需要借助切片的排序实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package mainimport ( "fmt" "math/rand" "sort" "time" ) func main () { rand.Seed(time.Now().UnixNano()) scoreMap := make (map [string ]int , 150 ) for i := 0 ; i < 100 ; i++ { key := fmt.Sprintf("stu%02d" , i) value := rand.Intn(100 ) scoreMap[key] = value } keys := make ([]string , 0 , 200 ) for k := range scoreMap { keys = append (keys, k) } sort.Strings(keys) for _, k := range keys { fmt.Println(k, scoreMap[k]) } }
9.4 其他相关 9.4.1 元素为 map 的切片 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package mainimport ( "fmt" ) func main () { var mapSlice = make ([]map [string ]string , 3 ) for index, v := range mapSlice { fmt.Printf("index:%d, value:%v \n" , index, v) } fmt.Println() mapSlice[0 ] = make (map [string ]string , 10 ) mapSlice[0 ]["name" ] = "张三" mapSlice[0 ]["password" ] = "123456" mapSlice[0 ]["address" ] = "济南" for index, v := range mapSlice { fmt.Printf("index:%d, value:%v\n" , index, v) } }
运行结果如下:
1 2 3 4 5 6 7 index:0 , value:map [] index:1 , value:map [] index:2 , value:map [] index:0 , value:map [address:济南 name:张三 password:123456 ] index:1 , value:map [] index:2 , value:map []
9.4.2 值为切片类型的 map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package mainimport "fmt" func main () { var sliceMap = make (map [string ][]string , 3 ) fmt.Println(sliceMap) k := "中国" value, ok := sliceMap[k] if !ok { value = make ([]string , 0 , 2 ) } value = append (value, "北京" , "上海" ) sliceMap[k] = value fmt.Println(sliceMap) }
1 2 3 4 5 6 7 8 9 10 11 package mainimport "fmt" func main () { var sliceMap = make (map [string ][]int , 3 ) sliceMap["北京" ] = []int {1 , 2 , 3 , 4 , 5 } fmt.Println(sliceMap) }
9.5 作业 9.5.1 判断字符串中汉字的数量 思路:
依次获取每个字符
判断字符是不是汉字
把汉字出现的次数累加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package mainimport ( "fmt" "unicode" ) func main () { s1 := "我是 CnPeng,我在济南" var count int for _, c := range s1 { if unicode.Is(unicode.Han, c) { count++ } } fmt.Println(count) }
9.5.2 统计单词出现的次数: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package mainimport ( "fmt" "strings" ) func main () { s1 := "how do you do " strSlice := strings.Split(s1, " " ) strMap := make (map [string ]int , 10 ) for _, w := range strSlice { if _, ok := strMap[w]; !ok { strMap[w] = 1 } else { strMap[w]++ } } for k, v := range strMap { fmt.Println(k, v) } }
9.5.2 回文判断 一个字符串从左向右读和从右向左读含义一致,就称为回文。如:
“上海自来水来自海上”、“山西运煤车煤运西山”、“黄山落叶松叶落山黄”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package mainimport "fmt" func main () { s1 := "山西运煤车煤运西山" r := make ([]rune , 0 , len (s1)) for _, c := range s1 { r = append (r, c) } for i := 0 ; i < len (r)/2 ; i++ { if r[i] != r[len (r)-1 -i] { fmt.Println("不是回文" ) return } } }