Golang通脈之map

Go語(yǔ)言中提供的映射關(guān)系容器為map戈稿,其內(nèi)部使用散列表(hash)實(shí)現(xiàn)。

map 是一種無序的鍵值對(duì)的集合动猬。map 最重要的一點(diǎn)是通過 key 來快速檢索數(shù)據(jù)捎稚,key 類似于索引,指向數(shù)據(jù)的值 map 是一種集合拥褂,所以可以像迭代數(shù)組和切片那樣迭代它娘锁。不過,map 是無序的饺鹃,無法決定它的返回順序莫秆,這是因?yàn)?map 是使用 hash 表來實(shí)現(xiàn)的,Go語(yǔ)言中的map是引用類型悔详,必須初始化才能使用镊屎。

使用map過程中需要注意的幾點(diǎn):

  • map是無序的,每次打印出來的map都會(huì)不一樣茄螃,它不能通過index獲取缝驳,而必須通過key獲取
  • map的長(zhǎng)度是不固定的,也就是和slice一樣,也是一種引用類型
  • 內(nèi)置的len函數(shù)同樣適用于map用狱,返回map擁有的key的數(shù)量
  • map的key可以是所有可比較的類型运怖,如布爾型、整數(shù)型夏伊、浮點(diǎn)型摇展、復(fù)雜型、字符串型……也可以鍵署海。

定義

Go語(yǔ)言中 map的定義語(yǔ)法如下:

map[KeyType]ValueType

其中吗购,

  • KeyType:表示鍵的類型。
  • ValueType:表示鍵對(duì)應(yīng)的值的類型砸狞。

**map類型的變量默認(rèn)初始值為nil捻勉,需要使用make()函數(shù)來分配內(nèi)存 (聲明并初始化) **。語(yǔ)法為:

make(map[KeyType]ValueType, [cap])

其中cap表示map的容量刀森,該參數(shù)雖然不是必須的踱启,但是我們應(yīng)該在初始化map的時(shí)候就為其指定一個(gè)合適的容量。

可以使用內(nèi)建函數(shù) make 研底,也可以使用 map 關(guān)鍵字來定義 Map:

/* 聲明變量埠偿,默認(rèn) map 是 nil */
var mapVariable map[KeyType]ValueType

/* 使用 make 函數(shù) */
mapVariable = make(map[keyType]ValueType)
rating := map[string]float32 {"C":5, "Go":4.5, "Python":4.5, "C++":2 }

如果不初始化 map,那么就會(huì)創(chuàng)建一個(gè) nil map榜晦。nil map 不能用來存放鍵值對(duì)

基本使用

map中的數(shù)據(jù)都是成對(duì)出現(xiàn)的:

func main() {
 scoreMap := make(map[string]int, 8)
 scoreMap["張三"] = 90
 scoreMap["小明"] = 100
 fmt.Println(scoreMap)
 fmt.Println(scoreMap["小明"])
 fmt.Printf("type of a:%T\n", scoreMap)
}

輸出:

map[小明:100 張三:90]
100
type of a:map[string]int

map也支持在聲明的時(shí)候填充元素冠蒋,例如:

func main() {
 userInfo := map[string]string{
  "username": "張三",
  "password": "123456",
 }
 fmt.Println(userInfo) //
}

判斷鍵是否存在

Go語(yǔ)言中有個(gè)判斷map中鍵是否存在的特殊寫法,格式如下:

value, ok := map[key]
func main() {
 /* 創(chuàng)建集合 */
   countryCapitalMap := make(map[string]string)
   
   /* map 插入 key-value 對(duì)乾胶,各個(gè)國(guó)家對(duì)應(yīng)的首都 */
   countryCapitalMap["France"] = "Paris"
   countryCapitalMap["Italy"] = "Rome"
   countryCapitalMap["Japan"] = "Tokyo"
   countryCapitalMap["India"] = "New Delhi"
 // 如果key存在ok為true,v為對(duì)應(yīng)的值抖剿;不存在ok為false,v為值類型的零值
 v, ok := countryCapitalMap["United States"]
 if ok {
  fmt.Println("Capital of United States is", captial)  
   }else {
      fmt.Println("Capital of United States is not present") 
   }
}

map的遍歷

Go語(yǔ)言中使用for range遍歷map。

func main() {
 countryCapitalMap := make(map[string]string)
   /* map 插入 key-value 對(duì)识窿,各個(gè)國(guó)家對(duì)應(yīng)的首都 */
   countryCapitalMap["France"] = "Paris"
   countryCapitalMap["Italy"] = "Rome"
   countryCapitalMap["Japan"] = "Tokyo"
   countryCapitalMap["India"] = "New Delhi"
 for k, v := range countryCapitalMap {
  fmt.Println(k, v)
 }
}

只想遍歷key的時(shí)候斩郎,可以按下面的寫法:

func main() {
 countryCapitalMap := make(map[string]string)
   /* map 插入 key-value 對(duì),各個(gè)國(guó)家對(duì)應(yīng)的首都 */
   countryCapitalMap["France"] = "Paris"
   countryCapitalMap["Italy"] = "Rome"
   countryCapitalMap["Japan"] = "Tokyo"
   countryCapitalMap["India"] = "New Delhi"
 for k := range countryCapitalMap {
  fmt.Println(k)
 }
}

注意: 遍歷map時(shí)的元素順序與添加鍵值對(duì)的順序無關(guān)喻频。

delete()函數(shù)刪除map元素

使用delete()內(nèi)建函數(shù)從map中刪除一組鍵值對(duì)缩宜,刪除函數(shù)不返回任何值,delete()函數(shù)的格式如下:

delete(map, key)

其中甥温,

  • map:表示要?jiǎng)h除鍵值對(duì)的map
  • key:表示要?jiǎng)h除的鍵值對(duì)的鍵
func main(){
 countryCapitalMap := make(map[string]string)
   /* map 插入 key-value 對(duì)锻煌,各個(gè)國(guó)家對(duì)應(yīng)的首都 */
   countryCapitalMap["France"] = "Paris"
   countryCapitalMap["Italy"] = "Rome"
   countryCapitalMap["Japan"] = "Tokyo"
   countryCapitalMap["India"] = "New Delhi"
 delete(countryCapitalMap, "France")//將"France":"Paris"從map中刪除
 for k,v := range scoreMap{
  fmt.Println(k, v)
 }
}

指定順序遍歷map

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開頭的字符串
  value := rand.Intn(100)          //生成0~99的隨機(jī)整數(shù)
  scoreMap[key] = value
 }
 //取出map中的所有key存入切片keys
 var keys = make([]string, 0, 200)
 for key := range scoreMap {
  keys = append(keys, key)
 }
 //對(duì)切片進(jìn)行排序
 sort.Strings(keys)
 //按照排序后的key遍歷map
 for _, key := range keys {
  fmt.Println(key, scoreMap[key])
 }
}

map類型的切片

下面的代碼切片中的元素為map類型時(shí)的操作:

func main() {
 var mapSlice = make([]map[string]string, 3)
 for index, value := range mapSlice {
  fmt.Printf("index:%d value:%v\n", index, value)
 }
 fmt.Println("after init")
 // 對(duì)切片中的map元素進(jìn)行初始化
 mapSlice[0] = make(map[string]string, 10)
 mapSlice[0]["username"] = "張三"
 mapSlice[0]["password"] = "123456"
 mapSlice[0]["address"] = "深圳"
 for index, value := range mapSlice {
  fmt.Printf("index:%d value:%v\n", index, value)
 }
}

value為切片類型的map

下面的代碼演示了map中值為切片類型的操作:

func main() {
 var sliceMap = make(map[string][]string, 3)
 fmt.Println(sliceMap)
 fmt.Println("after init")
 key := "中國(guó)"
 value, ok := sliceMap[key]
 if !ok {
  value = make([]string, 0, 2)
 }
 value = append(value, "北京", "上海")
 sliceMap[key] = value
 fmt.Println(sliceMap)
}

map是引用類型

與切片相似,map是引用類型姻蚓。當(dāng)將map分配給一個(gè)新變量時(shí)炼幔,它們都指向相同的內(nèi)部數(shù)據(jù)結(jié)構(gòu)。因此史简,一個(gè)的變化會(huì)反映另一個(gè):

func main() {  
    personSalary := map[string]int{
        "steve": 12000,
        "jamie": 15000,
    }
    personSalary["mike"] = 9000
    fmt.Println("Original person salary", personSalary)
    newPersonSalary := personSalary
    newPersonSalary["mike"] = 18000
    fmt.Println("Person salary changed", personSalary)

}

運(yùn)行結(jié)果:

Original person salary map[steve:12000 jamie:15000 mike:9000]  
Person salary changed map[steve:12000 jamie:15000 mike:18000] 

map不能使用操作符進(jìn)行比較。只能用來檢查map是否為空。否則會(huì)報(bào)錯(cuò):invalid operation: map1 == map2 (map can only be comparedto nil)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末圆兵,一起剝皮案震驚了整個(gè)濱河市跺讯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌殉农,老刑警劉巖刀脏,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異超凳,居然都是意外死亡愈污,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門轮傍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來暂雹,“玉大人,你說我怎么就攤上這事创夜『脊颍” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵驰吓,是天一觀的道長(zhǎng)涧尿。 經(jīng)常有香客問我,道長(zhǎng)檬贰,這世上最難降的妖魔是什么姑廉? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮翁涤,結(jié)果婚禮上桥言,老公的妹妹穿的比我還像新娘。我一直安慰自己迷雪,他們只是感情好限书,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著章咧,像睡著了一般倦西。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上赁严,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天扰柠,我揣著相機(jī)與錄音,去河邊找鬼疼约。 笑死卤档,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的程剥。 我是一名探鬼主播劝枣,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了舔腾?” 一聲冷哼從身側(cè)響起溪胶,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎稳诚,沒想到半個(gè)月后哗脖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡扳还,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年才避,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片氨距。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡桑逝,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出衔蹲,到底是詐尸還是另有隱情肢娘,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布舆驶,位于F島的核電站橱健,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏沙廉。R本人自食惡果不足惜拘荡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望撬陵。 院中可真熱鬧珊皿,春花似錦、人聲如沸巨税。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)草添。三九已至驶兜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間远寸,已是汗流浹背抄淑。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留驰后,地道東北人肆资。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像灶芝,于是被迫代替她去往敵國(guó)和親郑原。 傳聞我的和親對(duì)象是個(gè)殘疾皇子唉韭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • map是一種無序的基于key-value的數(shù)據(jù)結(jié)構(gòu),Go語(yǔ)言中的map是引用類型犯犁,必須初始化才能使用纽哥。 map的定...
    DevilRoshan閱讀 239評(píng)論 0 0
  • map是一種無序的基于key-value的數(shù)據(jù)結(jié)構(gòu),Go語(yǔ)言中的map是引用類型栖秕,必須初始化才能使用。 其中: K...
    learninginto閱讀 744評(píng)論 0 5
  • 總目錄:http://www.reibang.com/p/e406a9bc93a9 Golang - 子目錄:h...
    寒暄_HX閱讀 369評(píng)論 0 0
  • map map的底層實(shí)現(xiàn) golang中的map采用了HashTable的實(shí)現(xiàn)晓避,通過數(shù)組+鏈表實(shí)現(xiàn)的簇捍。一個(gè)哈希表會(huì)...
    xixisuli閱讀 3,809評(píng)論 0 1
  • 轉(zhuǎn)載自:https://halfrost.com/go_map_chapter_one/ https://half...
    HuJay閱讀 6,157評(píng)論 1 5