1. 程式人生 > 其它 >go語言map對映

go語言map對映

GO語言Map對映

目錄

GO語言Map 對映

Map 對映 是一種無序的鍵值對的集合。Map 最重要的一點是通過 key 來快速檢索資料,key 類似於索引,指向資料的值。

Map 是一種集合,所以我們可以像迭代陣列和切片那樣迭代它。不過,Map 是無序的,我們無法決定它的返回順序,這是因為 Map 是使用 hash 表來實現的。


值的型別 值的數量 值的索引
陣列: 相同 固定 下標
切片: 相同 動態 下標
結構體: 不相同 固定 屬性名
對映: 相同 動態 key

對映的實現

因為對映也是一個數據集合,所以,也可以使用類似處理陣列和切片的方式來迭代對映中的元素。但 對映是無序集合,所以即使以同樣的順序儲存鍵值對,每次迭代對映時,元素的順序也可能不一樣。

無序的原因是對映的本質使用了 散列表

map 在底層使用雜湊(hash)來實現的,在C:\Program Files\Go\src\hash\maphash\maphash.go ,map是一個hash陣列列表,由一個個bucket 組成

每一個元素都被稱為bucket的結構體,每一個bucket 可以儲存8個鍵值對,所有元素被hash演算法填入到陣列的bucket中,bucket填滿後,將通過 一個overflow指標來擴充套件一個bucket

,從而來形成連結串列,以此來解決hash衝突的問題。map就是一個bucket指標型的一堆陣列


定義 Map

可以使用內建函式 make 也可以使用 map 關鍵字來定義 Map:

//使用make 函式,建立一個對映,鍵的型別是string,值的型別是int
dict := make(map[string]int)


//建立一個對映,鍵值型別都是string,並進行初始化
teacher := map[string]string{"zhangsan":"Chinese","lisi":"English"}



//如果僅僅宣告map,而不進行 初始化,那麼就會建立一個空對映,空對映不能存放鍵值對.所以
//方法一:
var student map[string]string
student = make(map[string]string) //初始化

//方法二:
var student map[string]string = map[string]string

如果不初始化 map,那麼就會建立一個 nil map。nil map 不能用來存放鍵值對

對映的 鍵的可以是任何型別內建型別或者結構體都可以,需要確定這個值可以使用 == 運算子做比較。但是如切片,函式,這種引用型別的可以作為對映的鍵

對映的 值 可以是任何型別



元素賦值與獲取元素值

指定適當的型別鍵,並給這個鍵賦一個值就完成了對映的鍵值對賦值

賦值直接定義鍵值對,自動新增。鍵名必須唯一 .如果 鍵名重複,則會修改之前的值

如果想象獲取元素的值,使用鍵名獲取

//賦值
package main

import "fmt"

func main() {
	colors := map[string]string{}
	colors["red"] = "紅色"
	colors["blue"] = "藍色"
	fmt.Println(colors)
  //鍵名重複,則修改鍵的值
	colors["red"] = "紅"
	fmt.Println(colors)
}


//輸出結果:
map[blue:藍色 red:紅色]
map[blue:藍色 red:紅]

//通過鍵名,獲取對應的值
package main

import "fmt"

func main() {
	colors := map[string]string{}
	colors["red"] = "紅色"
	colors["blue"] = "藍色"
	//使用定義的對映,然後加上下標,下標為鍵名
	fmt.Println(colors["red"])
	fmt.Println(colors["blue"])
}

//輸出結果:
紅色
藍色


查詢與遍歷、

查詢

從對映去值時,有兩種方式。

第一種方式是:獲得值以及一個表達這個值是否存在的標誌

package main

import "fmt"

func main() {
	colors := map[string]string{}
	colors["red"] = "紅色"
	colors["blue"] = "藍色"

	//value 是red 對應的值。 exists 是布林型別,判斷鍵是否存在
	value, exists := colors["red"]
	fmt.Println(value, exists)
	
	if exists {
		fmt.Println("鍵存在")
	}

	//重新賦值value和exists。
	//value 是black 對應的值,如果black不存在,則返回string型別的預設值,即 空
	value, exists = colors["black"]
	fmt.Println(value, exists)
	if !exists {
		fmt.Println("鍵不存在")
	}
}
紅色 true
鍵存在
 false
鍵不存在

//輸出結果:

第二種方式是,只返回鍵對應的值,在判斷這個值是否為0值(int型別),或者是否為空值(string型別)。以此來判斷鍵是否存在。這種方式只能用在對映存的的值都是非0值或者非空值

package main

import "fmt"

func main() {
   colors := map[string]string{}
   colors["red"] = "紅色"
   colors["blue"] = "藍色"

   //獲取red 鍵對應的值。如果red鍵不存在,則結果為對應數值型別的預設值。string 型別預設為空
   value := colors["red"]
   //判斷這個鍵是否存在
   if value != "" {
   	fmt.Println("鍵存在")
   	fmt.Println(value)
   }
}

//輸出結果:
鍵存在
紅色

遍歷

通過使用range 可以迭代對映裡的所有值

package main

import "fmt"

func main() {
	colors := map[string]string{}
	colors["red"] = "紅色"
	colors["blue"] = "藍色"

	//使用range 遍歷所有資訊
	for key, value := range colors {
		fmt.Printf("key:%s,value:%s \n", key, value)
	}
}

//輸出結果:
key:red,value:紅色 
key:blue,value:藍色 


delete函式刪除集合的元素

package main

import "fmt"

func main() {
	colors := map[string]string{}
	colors["red"] = "紅色"
	colors["blue"] = "藍色"
	colors["yellow"] = "黃色"
	colors["green"] = "綠色"
	fmt.Println("刪除前:", colors)
	//刪除元素
	delete(colors, "red")
	fmt.Println("刪除後:", colors)
}

//輸出結果:
刪除前: map[blue:藍色 green:綠色 red:紅色 yellow:黃色]
刪除後: map[blue:藍色 green:綠色 yellow:黃色]

<br<

將對映傳遞給函式

在函式鍵傳遞對映並不會製造出該對映的副本。當傳遞對映給函式並對這個對映做了修改時,所有對這個對映的引用都會察覺到這個修改

package main

import "fmt"

func main() {
	colors := map[string]string{}
	colors["red"] = "紅色"
	colors["blue"] = "藍色"
	colors["yellow"] = "黃色"
	colors["green"] = "綠色"
	fmt.Println("修改前:", colors)

	//將對映作為值,傳遞給函式
	test(colors)
	fmt.Println("修改後:", colors)
}

func test(m map[string]string) {
	m["black"] = "黑色"
}


//輸出結果:
修改前: map[blue:藍色 green:綠色 red:紅色 yellow:黃色]
修改後: map[black:黑色 blue:藍色 green:綠色 red:紅色 yellow:黃色]