Go語言基礎之map

map概述

哈希表是一種巧妙而且使用的數據結構。它是一個無序的key-value對的集合,其中全部的key都是不一樣的,而後經過給定的key能夠在常數時間複雜度內檢索、更新或刪除對應的value。編程

Golang中,一個map就是一個哈希表的引用,又稱爲字段或者關聯數組。相似其餘編程語言的集合,在編程中是常常使用到。數組

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

map聲明舉例

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是無序的

map的使用

方式一:

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的增刪改查操做

map增長和更新

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切片

基本介紹

切片的數據類型若是是map,則稱爲slice of map(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]]
}

map排序

基本介紹

Golang中沒有一個專門的方法或者函數針對map的key進行排序。Golang中的map默認是無序的,注意也不是按照添加的順序存放的,每次遍歷,獲得的輸出可能不同。

map排序方法:先將key進行排序,而後根據key值遍歷輸出便可

map排序演示

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的容量達到後,再想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)
  • 統計一個字符串中每一個單詞出現的次數。好比:"how are you are you right",how=1,are=2,you=2,right=1
  • 觀察下面代碼,寫出最終的打印結果
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"])
}
相關文章
相關標籤/搜索