Skip to content

Files

Latest commit

Oct 26, 2022
d81d36e · Oct 26, 2022

History

History

lesson15

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Nov 3, 2021
Oct 28, 2021
Oct 28, 2021
Oct 28, 2021
Oct 31, 2021
Oct 26, 2022

readme.md

map集合

定义

Go语言里的map底层是通过hash实现的,是一种无序的基于<key, value>对组成的数据结构,key是唯一的,类似python的dict。

map必须初始化后才能写map。

如果只是声明map,但没有初始化,只能读,不能写。参考下面的例子的说明:

package main

import "fmt"

func main() {
	var counter map[string]int
	/*
	map没有初始化,读map相当于读了一个空map
	下例中:value是int的零值0,ok是false
	*/
	value, ok := counter["a"]
	fmt.Println(value, ok)

	/*counter没有初始化,给counter赋值会在运行时报错
	  panic: assignment to entry in nil map
	*/
	counter["a"] = 1
	fmt.Println(counter)
}
  • 语法

    var map_var map[key_data_type]value_data_type = map[key_data_type]value_data_type{}
    
    var map_var = map[key_data_type]value_data_type{}
    
    map_var := map[key_data_type]value_data_type{}
    
    /*cap是map容量,超过后会自动扩容*/
    map_var := make(map[key_data_type]value_data_type, [cap]) 
  • 示例

    package main
    
    import "fmt"
    
    func main() {
        var dict map[string]int = map[string]int{}
        dict["a"] = 1
        fmt.Println(dict)
        
        var dict2 = map[string]int{}
        dict2["b"] = 2
        fmt.Println(dict2)
        
        dict3 := map[string]int{"test":0}
        dict3["c"] = 3
        fmt.Println(dict2)
        
        dict4 := make(map[string]int)
        dict4["d"] = 4
        fmt.Println(dict4)
    }

使用

  • 判断key在map里是否存在

    • 语法。

      value, is_exist := map[key]

      如果key存在,那is_exist就是true, value是对应的值。否则is_exist就是false, value是map的value数据类型的零值。

      注意: 如果key不存在,通过map[key]访问不会给map自动插入这个新key。C++是会自动插入新key的,两个语言不一样。如果确定key存在,可以直接使用map[key]拿到value。

    • 示例

      package main
      
      import "fmt"
      
      func main() {
          // 构造一个map
          str := "aba"
          dict := map[rune]int{}
          for _, value := range str{
              dict[value]++
          }
          fmt.Println(dict) // map[97:2 98:1]
          
          // 访问map里不存在的key,并不会像C++一样自动往map里插入这个新key
          value, ok := dict['z']
          fmt.Println(value, ok) // 0 false
          fmt.Println(dict) // map[97:2 98:1]
          
          // 访问map里已有的key
          value2 := dict['a']
          fmt.Println(value2) // 2
      }
  • 遍历map:使用range迭代,参见lesson14

  • len(map):通过内置的len()函数可以获取map里<key, value>对的数量

    counter := make(map[string]int)
    fmt.Println(len(counter))
    counter["a"] = 1
    fmt.Println(len(counter))
  • map作为函数形参,可以在函数体内部改变外部实参的值,原理参见Go有引用传递么?。示例如下:

    package main
    
    import "fmt"
    
    
    
    func buildMap(str string, m map[rune]int) {
    	/*函数内对map变量m的修改会影响main里的实参mapping*/
    	for _, value := range str {
    		m[value]++
    	}
    }
    
    
    func main() {
    	mapping := map[rune]int{}
    	str := "abc"
    	buildMap(str, mapping)
    
    	/*
    	mapping的值被buildMap修改了
    	*/
    	for key, value := range mapping {
    		fmt.Printf("key:%v, value:%d\n", key, value)
    	}
    }

delete函数

  • 删除key,参数为map和对应的key。允许删除一个不存在的key,对map无任何影响。

    package main
    
    import "fmt"
    
    func main() {
        dict :=  map[string]int{"a":1, "b":2}
        fmt.Println(dict) // map[a:1 b:2]
        
        // 删除"a"这个key
        delete(dict, "a")
        fmt.Println(dict) // map[b:2]
        
        // 删除"c"这个不在的key,对map结果无影响
        delete(dict, "c")
        fmt.Println(dict) // map[b:2]
    }

注意事项

  • key必须支持==和!=比较,才能用作map的key。

    因此切片slice,函数类型function,集合map,不能用作map的key

  • map不是并发安全的,并发读写要加锁