Go基礎編程——map

map
1、類 似 其 它 浯 言 中 的 唁 希 表 或 者 字 典 , 以 key-value形式存儲數據 :
2、Key必須 是 支 持==或 ! = 比 較 運 算 的 類 型 , 不 可 以 是函數、 map或者slice
3、Map查找 比 線 性 搜 索 快 很 多 , 但 比 使 用 索 引(數組,Slice等) 訪 問 數 據 的 類 型 慢 100 倍
4、Map使用make()創建 , 支 持:=這 種 簡 寫 方 式
5、make([keyType]valueType, cap) , cap 表 示 容 量 , 可 省 略
6、超 出 容 量 時 會 自 動 擴 容 , 但 盡 量 提供 一 個 臺 理 的 初 始 值
7、使用len()獲 取 元 素 個數
8、鍵值 對 不 存 在 時 自 動 添 加 , 使 用delete() 刪 除 某鍵值對
9、使 用 for range 對 map 和Slice 進 行 迭 代 操 作
創建一個空的map

m:=map[int]string{}
fmt.Println(m)

其中int是key的類型,string是value的類型。
使用make()來創建map的方式如下:

n:=make(map[int]string)

m[1]="Hello"

可以使用這樣的方式給map賦值。

a:=m[1]

使用這樣的方式取出值。同時刪除一個值可以使用如下程序來完成:

m:=map[int]string{}
m[1]="Hello"
a:=m[1]
fmt.Println(m)
delete(m,1)
fmt.Println(m)
/*n:=make(map[int]string)
fmt.Println(n)*/
fmt.Println(a)

運行結果

map[1:Hello]
map[]
Hello

這樣就實現了刪除一個元素。delete(m,1)第一個參數m是指的要刪除的元素所在的map類型,1代表要刪除的元素的key值。
當然企業級開發都是使用複雜的map來實現功能的,接下來就試試:

m:=make(map[int]map[int]string)
m[1]=make(map[int]string)
fmt.Println(m)
m[1][1]="Hello"
a:=m[1][1]
fmt.Println(m)
fmt.Println(a)

運行結果

map[1:map[]]
map[1:map[1:Hello]]
Hello

可以看到第一次初始化只是對最外層進行了初始化,第二次纔是到裏層。這裏有兩種方法檢查map是否被初始化。
第一種方法就是直接取那個值,如下

m:=make(map[int]map[int]string)
m[1]=make(map[int]string)
fmt.Println(m)
//m[1][1]="Hello"
a:=m[1][1]
fmt.Println(m)
fmt.Println(a)

這時候fmt.Println(a)得到就是一個空字符串,
這裏推薦第二種方法,使用多返回值的特性返回一個bool類型更加好判斷是否有值,以便在合適的時候給它初始化。示例程序如下:

m:=make(map[int]map[int]string)
m[1]=make(map[int]string)
fmt.Println(m)
//m[1][1]="Hello"
a,ok:=m[1][1]
if !ok{
   m[1][1]="Hello"
}
a=m[1][1]
fmt.Println(m)
fmt.Println(a)

運行結果

map[1:map[]]
map[1:map[1:Hello]]
Hello

這樣就實現了,首先判斷出某個值未被賦值的時候給他在合適的地方初始化。記住一個核心點,多個map嵌套的時候每一級都要進行單獨的初始化。
Slice與map結合的使用場景

sm:=make([]map[int]string,3)
for _,v:=range sm{
   v=make(map[int]string,1)
   v[1]="China"
   fmt.Println(v)
}
fmt.Println(sm)

運行結果

map[1:China]
map[1:China]
map[1:China]
[map[] map[] map[]

這個就是以map爲類型,初始值爲3個的Slice
這種形式初始化的sm是空值,因爲循環遍歷出來的v只是一個拷貝,在計算機中的地址不是原來的內存地址,所以,給拷貝出來的v賦值不會影響到sm中對應的v值。下邊來看看每次的循環拷貝出來的內存地址和原來sm的內存地址不一樣,就可以解釋了,看如下程序:

sm:=make([]map[int]string,3)
for _,v:=range sm{
   v=make(map[int]string,1)
   v[1]="China"
   fmt.Println(v)
   fmt.Printf("%p\n",v)
}
fmt.Println(sm)
fmt.Printf("%p\n",sm)

運行結果

map[1:China]
0xc042068060
map[1:China]
0xc042068090
map[1:China]
0xc0420680c0
[map[] map[] map[]]
0xc0420023e0

可以看出每次拷貝都是放在不同內存地址。一般情況我們希望通過循環來給sm初始化賦值,這時候只需要獲取返回來的索引就可以解決問題,看如下解決辦法:

sm:=make([]map[int]string,3)
for i,_:=range sm{
   sm[i]=make(map[int]string,1)
   sm[i][1]="China"
   fmt.Println(sm[i])
   fmt.Printf("%p\n",sm[i])
}
fmt.Println(sm)
fmt.Printf("%p\n",sm)

運行結果

map[1:China]
0xc04207a060
map[1:China]
0xc04207a090
map[1:China]
0xc04207a0c0
[map[1:China] map[1:China] map[1:China]]
0xc0420443a0

這樣以索引的形式賦值,就不會是空的,索引是在內存中是唯一的,這樣就就能夠對迭代對象進行直接拷貝。
map是無序性的,但是很多時候需要map間接的成爲有序的,這時候就需要藉助Slice,主要是通過給map的key值進行排序來達到對map的排序,看如下程序:

m:=map[int]string{1:"a",2:"b",3:"c",4:"d",5:"e"}
s:=make([]int,len(m))
i:=0
for k,_:=range m  {
   s[i]=k
   i++
}
sort.Ints(s)
fmt.Println(s)
for i=1;i<=len(s);i++{
for k,_:=range m{
   if k==i{
      a:=m[k]
      fmt.Print(a)
   }
}
}

運行結果

[1 2 3 4 5]
abcde

思考

使用for range嘗試將類型爲map[int]string的鍵和值進行交換,是它變成map[string]int
如下所示;

m1:=map[int]string{1:"a",2:"b",3:"c"}
        m2:=make(map[string]int)
        for k,v:=range m1{
            m2[v]=k
        }
        fmt.Print(m1,m2)

運行結果

map[1:a 2:b 3:c] map[a:1 b:2 c:3]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章