Golang數(shù)據(jù)類(lèi)型之Map
目錄
1、概述
2、聲明
3、初始化
4、操作
4.1 獲取元素的數(shù)量
4.2 訪問(wèn)
4.3 判斷 key 是否存在
4.4 修改和增加
4.5 刪除
4.6 遍歷
4.7 多級(jí) map

1、概述
map(映射)是存儲(chǔ)一系列無(wú)序的key/value對(duì),通過(guò)key來(lái)對(duì)value進(jìn)行操作(增、刪、改、查)。映射的key只能為可使用==運(yùn)算符的值類(lèi)型(字符串、數(shù)字、布爾、數(shù)組),value可以為任意類(lèi)型

map的設(shè)計(jì)也被稱(chēng)為The dictionary problem,它的任務(wù)是設(shè)計(jì)一種數(shù)據(jù)結(jié)構(gòu)用來(lái)維護(hù)一個(gè)集合的數(shù)據(jù),并且可以同時(shí)對(duì)集合進(jìn)行增刪查改的操作
Go里的map用于存放key/value對(duì),在其它地方常稱(chēng)為hash、dictionary、關(guān)聯(lián)數(shù)組,這幾種稱(chēng)呼都是對(duì)同一種數(shù)據(jù)結(jié)構(gòu)的不同稱(chēng)呼,它們都用于將key經(jīng)過(guò)hash函數(shù)處理,然后映射到value,實(shí)現(xiàn)一一對(duì)應(yīng)的關(guān)系
映射是存儲(chǔ)一系列無(wú)序的key/value對(duì),通過(guò)key來(lái)對(duì)value進(jìn)行操作(增、刪、改、查)
2、聲明
map的key至少可以有==、!=運(yùn)算,值可以為整數(shù)、字符串、數(shù)組
value可以是任意類(lèi)型
map聲明需要指定組成元素key和value的類(lèi)型,在聲明后,會(huì)被初始化為nil,表示暫不存在的映射 0
var scores map[string]int // nil映射,光聲明map類(lèi)型但是沒(méi)有初始化
fmt.Printf("%T %#v\n", scores, scores)
fmt.Println(scores == nil) // true
關(guān)于nil map和空map
空map是不做任何賦值的map
a := map[int]string
nil map,它將不會(huì)做任何初始化,不會(huì)指向任何數(shù)據(jù)結(jié)構(gòu)
var a map[int]string
如何map沒(méi)初始化,直接賦值會(huì)報(bào)空指針
var a map[int]string
var b []string
fmt.Printf("%p, %p\n", a, b)
// a[0] = "a"
// b[0] = "a"
a = map[int]string{0: "a"}
b = []string{"a"}
fmt.Printf("%p, %p\n", a, b)
所以,map類(lèi)型實(shí)際上就是一個(gè)指針, 具體為*hmap
3、初始化
a) 使用字面量初始化并賦值map[ktype]vtype{k1:v1, k2:v2, …, kn:vn}
b) 使用字面量初始化空映射map[ktype]vtype{ }
c) 使用make函數(shù)初始化make(map[ktype]vtype),通過(guò)make函數(shù)創(chuàng)建映射,指定容量
//scores = map[string]int{}
scores = map[string]int{"a": 8, "b": 9, "c":10}
fmt.Println(scores)
//scores = make(map[string]int, 8)
// 聲明map的同時(shí)完成初始化
b := map[int]bool{
1: true,
2: false,
}
4、操作
4.1 獲取元素的數(shù)量
使用len函數(shù)獲取映射元素的數(shù)量
4.2 訪問(wèn)
當(dāng)訪問(wèn)key存在與映射時(shí)則返回對(duì)應(yīng)的值,否則返回值類(lèi)型的零值
4.3 判斷 key 是否存在
通過(guò)key訪問(wèn)元素時(shí)可接收兩個(gè)值,第一個(gè)值為value,第二個(gè)值為bool類(lèi)型表示元
素是否存在,若存在為true,否則為false
4.4 修改和增加
使用key對(duì)映射賦值時(shí)當(dāng)key存在則修改key對(duì)應(yīng)的value,若key不存在則增加 key和value
4.5 刪除
使用delete函數(shù)刪除映射中已經(jīng)存在的key
4.6 遍歷
可通過(guò)for-range對(duì)映射中個(gè)元素進(jìn)行遍歷,range返回兩個(gè)元素分別為映射的key和value
上述操作示例:
// 增刪改查
// key
fmt.Println(scores["a"]) // 8
fmt.Println(scores["d"]) // 0 key不存在則為0,但這樣不準(zhǔn)確
// v, ok := scores["c"]
// if ok {
if v, ok := scores["c"]; ok {
fmt.Println(v)
fmt.Println(ok) // false 判斷某個(gè)鍵是否存在
}
scores["b"] = 10
fmt.Println(scores)
scores["d"] = 20
fmt.Println(scores)
// 刪除
delete(scores, "c") // 按照key刪除
fmt.Println(scores)
// 獲取當(dāng)前映射元素的數(shù)量
fmt.Println(len(scores))
// 遍歷key、value
for k, v := range scores {
fmt.Println(k, v) // 遍歷的順序和添加的順序是沒(méi)有任何關(guān)系的
}
// 只遍歷map中的key
for k := range scores {
fmt.Println(k) // 遍歷的順序和添加的順序是沒(méi)有任何關(guān)系的
}
// 只遍歷map中的value
for _, v := range scores {
fmt.Println(v)
}
按照某個(gè)固定順序遍歷 map
默認(rèn)情況下,對(duì)map遍歷后都是無(wú)序的,可以通過(guò)將map中的key存到切片中,然后對(duì)切片元素排序,最終實(shí)現(xiàn)對(duì)map的有序遍歷
package main
import (
"fmt"
"math/rand"
"sort"
"time"
)
func main() {
rand.Seed(time.Now().UnixNano()) // 初始化隨機(jī)數(shù)種子
var scoreMap = make(map[string]int, 200)
for i := 0; i < 100; i++ {
key := fmt.Sprintf("stu%02d", i) // 生成stu開(kāi)頭的字符串
value := rand.Intn(100) // 生成0~99的隨機(jī)整數(shù)
scoreMap[key] = value
}
// 正常遍歷,無(wú)序
//for k, v := range scoreMap{
// fmt.Println(k, v)
//}
// 有序遍歷,按照key從小到大的順序遍歷scoreMap
// 1、取出map中的所有key存入切片keys
var keys = make([]string, 0, 200) // 定義切片
for key := range scoreMap { // 把key添加到切片中
keys = append(keys, key)
}
// 2、對(duì)切片進(jìn)行排序
sort.Strings(keys)
// 3、按照排序后的key遍歷map
for _, key := range keys {
fmt.Println(key, scoreMap[key])
}
}
4.7 多級(jí) map
多級(jí)映射:定義映射的映射
// 名字 => 映射[字符串]字符串{"1", "2", "3"}
var users map[string]map[string]string
users = map[string]map[string]string{"北京": {"1": "朝陽(yáng)", "2": "東城", "3": "西城"}}
fmt.Printf("%T, %#v\n", users, users)
_, ok := users["上海"]
fmt.Println(ok) // false
users["上海"] = map[string]string{"1": "浦東", "2": "徐匯", "3": "靜安"}
fmt.Println(users) // map[上海:map[1:浦東 2:徐匯 3:靜安] 北京:map[1:朝陽(yáng) 2:東城 3:西城]]
users["上海"]["3"] = "虹橋"
fmt.Println(users) // map[上海:map[1:浦東 2:徐匯 3:虹橋] 北京:map[1:朝陽(yáng) 2:東城 3:西城]]
delete(users["北京"], "1")
fmt.Println(users) // map[上海:map[1:浦東 2:徐匯 3:虹橋] 北京:map[2:東城 3:西城]]
