map的使用和细节

基本语法
var 变量名 map[key-type]value-type 例如 var a map[int]string->key是int类型,value是string类型。
注意:通常key为int,string类型,而slice,map和function不可以作为Key,因为这几个没法用==来判断。

func main() {
	//map的声明  make的作用给map分配数据空间
	var a map[string]string = make(map[string]string)
	a["no1"] = "宋江"
	a["no2"] = "吴用"
	a["no1"] = "武松" //key不能重读,武松会覆盖松江
	a["no3"] = "吴用"
	fmt.Println(a) //map[no1:武松 no2:吴用 no3:吴用]

	//数组在声明的时候已经分配数据空间了
	var arr [5]int
	arr[1] = 1
	fmt.Println(arr) //[0 1 0 0 0]

}
  1. map使用前一定要make。
  2. map的key是不能重复的,如果重复了,则以最后这个key-value为准。
  3. map的value是可以相同的。
  4. map的key-value是无序的。
  5. make是一个内置函数,初始map的时候分配的创建取决于size。但产生的映射长度为0。size可以省略,这种情况下可以分配一个小的大小。

map的使用方式

func main() {
	//方式1 声明后再分配空间
	var a map[string]string
	a = make(map[string]string, 10)
	a["no1"] = "宋江"
	a["no2"] = "吴用"
	a["no1"] = "武松"
	a["no3"] = "吴用"
	fmt.Println(a) //map[no1:武松 no2:吴用 no3:吴用]

	//方式2 类型判断直接make
	cities := make(map[string]string)
	cities["no1"] = "北京"
	cities["no2"] = "天津"
	cities["no3"] = "上海"
	fmt.Println(cities) //map[no1:北京 no2:天津 no3:上海]

	//方式3 初始化的时候就赋值
	var heroes map[string]string = map[string]string{
		"hero1": "猪猪侠",
		"hero2": "钢铁侠",//这里结尾也要有逗号
	}
	fmt.Println(heroes) //map[hero1:猪猪侠 hero2:钢铁侠]

}

map的增删查改操作:

  • map的增加和更新:map["key"]=value //如果Key没有则增加,如果Key存在就是修改。
  • map的删除:delete(map,key),delete是一个内置函数,如果key存在,就删除key-value,如果Key不存在,不做任何变化,也不会报错。
func main() {
	//定义个map
	var a map[string]string
	a = make(map[string]string, 10)
	a["no1"] = "宋江"
	a["no2"] = "吴用"
	a["no1"] = "武松" //替换no1的value
	a["no3"] = "吴用"
	a["no3"] = "吴用1111" //替换no3的value
	fmt.Println(a)      //map[no1:武松 no2:吴用 no3:吴用1111]
	//删除
	delete(a, "no3")
	fmt.Println(a) //map[no1:武松 no2:吴用]
}

说明:如果要清空整个map我们可以遍历整个map依次删除key。或者把map的指向一个新的空间,那么以前的Map空间会被GC回收。

  • map的查找: value,boole := map[key]
    //引用上个代码块的map变量名是a
	value, b := a["no1"]
	if b {
		fmt.Println("no1的值是", value)
	} else {
		fmt.Println("no1的值是空的")
	}

map的遍历:

func main() {
	//定义个map
	var a map[string]string
	a = make(map[string]string, 10)
	a["no1"] = "宋江"
	a["no2"] = "吴用"
	a["no3"] = "吴用"
	//遍历map只能用for range
	for key, value := range a {
		fmt.Println("key=", key, "value=", value)
	}
	//定义一个map
	stus := make(map[string]map[string]string)
	stus["no1"] = make(map[string]string, 3)
	stus["no1"]["name"] = "张三"
	stus["no1"]["sex"] = "男"
	stus["no1"]["address"] = "北京长安街"

	stus["no2"] = make(map[string]string, 3)
	stus["no2"]["name"] = "小红"
	stus["no2"]["sex"] = "女"
	stus["no2"]["address"] = "上海红灯区"

	for k1, v1 := range stus {
		fmt.Println("k1=", k1)
		for k2, v2 := range v1 {
			fmt.Println("k2=", k2, "v2=", v2)
		}
	}
}

map切片
切片的数据类型如果是Map,那么这样的数据结构就是map切片,这样使用则map个数就可以动态变化的。

func main() {
	//map切片  其实外层就是一个切片  里面的数据是map[string]string类型
	monsters := make([]map[string]string, 2)
	//增加数据
	if monsters[0] == nil {
		//切片的第一个元素是空的 那么就放入信息
		monsters[0] = make(map[string]string)
		monsters[0]["name"] = "牛魔王"
		monsters[0]["age"] = "500岁"
	}
	if monsters[1] == nil {
		monsters[1] = make(map[string]string)
		monsters[1]["name"] = "玉兔精"
		monsters[1]["age"] = "100岁"
	}
	//monsters切片分配了2个内存空间 如果要继续加元素需要append函数
	monsters = append(monsters, map[string]string{
		"name": "红孩儿",
		"age":  "200岁",
	})
	fmt.Println(monsters)//[map[age:500岁 name:牛魔王] map[age:100岁 name:玉兔精] map[age:200岁 name:红孩儿]]

}

map的排序

  1. golang中的map默认是无序的,也就是说不是按添加的顺序存放的,每次遍历,得到的输出可能不一样。
  2. 正对上面的问题,其实解决思路也很简单:定义一个切片存放map的key。 var keys = []int
    3 对切片进行排序,使用内置函数sort.Ints(keys),keys的定义的切片变量名字,类似是[]int
    4 遍历切片,根据key找到map中的value。
func main() {
	//定义一个map
	m := make(map[int]int)
	m[10] = 100
	m[1] = 13
	m[4] = 56
	m[8] = 90
	fmt.Println(m)
	//定义一个切片
	var keys []int
	//把map的key放入切片中
	for k, _ := range m {
		keys = append(keys, k)
	}
	//遍历切片按key输出map的value
	for _, k := range keys {
		fmt.Printf("%v:%v \n", k, m[k])
	}
}

map细节

  1. map是引用类型,遵守引用传递的机制,在一个函数接收Map,修改后会直接修改原来的值。
  2. map可以动态增长容量。
  3. map的value也经常使用struct类型,更适合管理复杂的数据。
posted @ 2024-01-25 17:10  程序马2023  阅读(66)  评论(0)    收藏  举报