哈希表是一種巧妙而且使用的數據結構。它是一個無序的key-value
對的集合,其中全部的key都是不一樣的,而後經過給定的key能夠在常數時間複雜度內檢索、更新或刪除對應的value。編程
Golang中,一個map就是一個哈希表的引用,又稱爲字段或者關聯數組。相似其餘編程語言的集合,在編程中是常常使用到。數組
var map 變量名 map[keytype]valuetype
key的類型數據結構
Golang中的map的key能夠是不少種類型,好比bool,數字,string,指針,channel,還能夠是接口,結構體,數組。key對應的類型必須支持==
比較運算符的數據類型,因此map能夠經過測試key是否相等來判斷是否已經存在。app
一般key爲int、string。編程語言
注意:slice,map還有function不能夠做爲key,由於這幾個無法用==
來判斷。函數
valuetype的類型測試
valuetype的類型沒有任何的限制指針
一般爲:數字(整數,浮點數),string,map,struct。code
var a map[string]string var a map[string]int var a map[int]string var a map[string]map[string]string
注意:聲明是不會分配內存的,初始化須要使用make,分配內存後才能賦值和使用。內建函數make分配並初始化一個類型爲切片、映射、或通道的對象。對象
map聲明案例演示:
func main(){ var a map[string]string a = make(map[string]string, 10) //使用make函數給map分配數據空間 a["no1"] = "tom" a["no2"] = "jerry" a["no3"] = "jack" a["no1"] = "alice" fmt.Println(a) }
對上面代碼的說明:
map在使用前必定要make
map的key是不能重複的。若是重複了,則以最後這個key-value爲準
map的value是能夠相同的
map的key-value是無序的
方式一:
var a map[string]string //在使用map前,須要先make,make的做用是給map分配數據空間 a = make(map[string]string, 10) a["no1"] = "tom" a["no2"] = "jerry" a["no3"] = "jack" a["no1"] = "alice" fmt.Println(a)
方式二:
cities := make(map[string]string) cities["no1"] = "北京" cities["no2"] = "天津" cities["no3"] = "上海" fmt.Println(cities)
方式三:
heroes := map[string]string{ "heroes1" : "鋼鐵俠" "heroes2" : "蜘蛛俠" "heroes3" : "綠巨人" } heroes["heroes4"] = "黑寡婦" fmt.Println("heroes=", heroes)
案例演示:
案例需求:存放三個學生的信息,每一個學生有name和sex信息
students := make(map[string]map[string]string, 3) //對於map要先使用make聲明,students中的value也是map,因此對於每一個key對應的值都須要map students["stu01"] = make(map[string]string, 2) students["stu01"]["name"] = "tom" students["stu01"]["sex"] = "男" students["stu02"] = make(map[string]string, 2) students["stu02"]["name"] = "mary" students["stu02"]["sex"] = "女" fmt.Println(students) fmt.Println(students["stu01"]) fmt.Println(students["stu01"]["name"])
map["key"] = value //若是key尚未,就是增長,若是key存在就是修改
刪除map中的一個鍵值對,使用內置函數delete
。使用方法:delete(map, "key")
,若是key存在,就刪除key-value,若是不存在,不操做,但也不會報錯。
cities := make(map[string]string) cities["no1"] = "北京" cities["no2"] = "天津" cities["no3"] = "上海" fmt.Println(cities) //使用delete內置函數刪除cities中的鍵值對 delete(cities, "no1") fmt.Println(cities) delete(cities, "no4") fmt.Println(cities)
在Golang中沒有一下刪除整個map中的key的函數。這時能夠遍歷一下key逐個刪除,或者map = make(...)
,make一個新的,讓原來的成爲垃圾,被gc回收。
//方法一:使用make,開闢一個新的map空間 cities = make(map[string]string) fmt.Println(cities) //方法二:遍歷key,逐個刪除 for key, _ := range cities { delete(cities, cities[key]) }
map的查找仍是經過key來進行查找,咱們能夠封裝一個函數,參數爲key和map,返回值爲bool類型;若是找到返回true,不然返回false。代碼以下:
func findRes(key string, m map[string]string) bool { _, ok := m[key] // 判斷某個鍵是否存在 if ok { return true } else { return false } } func main() { cities := make(map[string]string) cities["no1"] = "北京" cities["no2"] = "天津" cities["no3"] = "上海" fmt.Println(cities) fmt.Println(findRes("no1", cities)) fmt.Println(findRes("no4", cities)) }
map的遍歷使用使用for-range的結構遍歷
func main() { cities := make(map[string]string) cities["no1"] = "北京" cities["no2"] = "天津" cities["no3"] = "上海" fmt.Println(cities) for k, v := range cities { fmt.Printf("k=%v v=%v\n", k, v) } //變量map的map students := make(map[string]map[string]string, 3) //對於map要先使用make聲明,students中的value也是map,因此對於每一個key對應的值都須要map students["stu01"] = make(map[string]string, 2) students["stu01"]["name"] = "tom" students["stu01"]["sex"] = "男" students["stu02"] = make(map[string]string, 2) students["stu02"]["name"] = "mary" students["stu02"]["sex"] = "女" for key1, value1 := range students { fmt.Println("key1=", key1) for key2, value2 := range value1 { fmt.Printf("\tkey2=%v value2=%v\n", key2, value2) } } }
使用len()
內建函數能夠返回map的長度:
func main() { cities := make(map[string]string) cities["no1"] = "北京" cities["no2"] = "天津" cities["no3"] = "上海" fmt.Println(cities) //變量map的map students := make(map[string]map[string]string, 3) //對於map要先使用make聲明,students中的value也是map,因此對於每一個key對應的值都須要map students["stu01"] = make(map[string]string, 2) students["stu01"]["name"] = "tom" students["stu01"]["sex"] = "男" students["stu02"] = make(map[string]string, 2) students["stu02"]["name"] = "mary" students["stu02"]["sex"] = "女" fmt.Println(len(students)) //2 fmt.Println(len(cities)) //3 }
切片的數據類型若是是map,則稱爲slice of map(map切片),這樣map的個數就能夠動態變化。
案例演示:
案例需求:使用一個map來記錄學生的信息name和age,而且學生的個數能夠動態增長
func main() { //聲明一個students的map切片 var students []map[string]string students = make([]map[string]string, 2) //先存放兩個學生 if students[0] == nil { students[0] = make(map[string]string, 2) students[0]["name"] = "tom" students[0]["age"] = "24" } if students[1] == nil { students[1] = make(map[string]string, 2) students[1]["name"] = "mary" students[1]["age"] = "20" } //越界panic: runtime error: index out of range [2] with length 2 //if students[2] == nil { // students[2] = make(map[string]string, 2) // students[2]["name"] = "jerry" // students[2]["age"] = "20" //} //使用append函數動態的增長students student := map[string]string { "name" : "jerry", "age" : "20", } students = append(students, student) fmt.Println(students) //[map[age:24 name:tom] map[age:20 name:mary] map[age:20 name:jerry]] }
Golang中沒有一個專門的方法或者函數針對map的key進行排序。Golang中的map默認是無序的,注意也不是按照添加的順序存放的,每次遍歷,獲得的輸出可能不同。
map排序方法:先將key進行排序,而後根據key值遍歷輸出便可
func main() { rand.Seed(time.Now().UnixNano()) //初始化隨機種子 // 聲明一個scoreMap用來存學生的成績 var scoreMap = make(map[string]int, 200) for i := 0; i < 100; i++ { key := fmt.Sprintf("stu%02d", i) //生成stu開頭的字符串 scoreMap[key] = rand.Intn(100) //生成0-100之間的隨機數做爲學生的成績 } var keys = make([]string, 0, 100) //取出scoreMap中的key存儲到[]key切片中 for key := range scoreMap { keys = append(keys, key) } //對切片進行排序 sort.Strings(keys) //使用排序好的key對scoreMap進行遍歷 for _, k := range keys { fmt.Println(k, scoreMap[k]) } }
map是引用類型,遵照引用類型傳遞的機制,在一個函數接收map,修改之,則會修改原來的map
map的容量達到後,再想map增長元素,會自動擴容,並不會發生panic,也就是說map能動態的增加key-value
map的value也常常使用struct類型,更適合管理複雜的數據
type Stu struct { name string age int } func main() { // 使用map來存儲Stu結構體 // 學生的學號做爲map的key,由於學號惟一,學生的姓名和年齡做爲Stu結構體的字段 var stuMap = make(map[string]Stu, 10) stuMap["no1"] = Stu{"tom", 19} stuMap["no2"] = Stu{"jerry", 20} fmt.Println(stuMap) // map[no1:{tom 19} no2:{jerry 20}] }
map[string]map[string]string
的map類型,key表示用戶名,是惟一的,不能夠重複;若是這個用戶名存在,就將其密碼修改爲"666666",若是不存在就增長這個用戶的信息(nickname和密碼pwd)func main() { type Map map[string][]int m := make(Map) s := []int{1, 2} s = append(s, 3) fmt.Printf("%+v\n", s) m["q1mi"] = s s = append(s[:1], s[2:]...) fmt.Printf("%+v\n", s) fmt.Printf("%+v\n", m["q1mi"]) }