Go语言复合数据类型之map

Go语言复合数据类型之map

map的定义

哈希表是一个无序的key/value对的集合,要求所有的key必须不同,然后通过给定的key可以在O(1)内检索、更新或者删除对应的value。

go语言中map就是一个哈希表,其表达形式为map[key] = value ,key在map中是同一种数据类型,其中key必须是支持比较运算符的类型,所以map可以通过测试key是否相等来判断此key是否已经存在。注意,不建议使用float浮点数来作为key,因为最坏的情况可能是出现NaN和任务浮点数都不想等。对于value类型则没有限制。

map的初始化

使用内置make函数初始化
	ages := make(map[string]int,len,cap) //len 和cap 可以省略
	ages["zhangsan"] = 20
	ages["lisi"] = 16
	//map[lisi:16 zhangsan:20]

此时key为string 类型,value为int类型。

使用map字面值语法初始化
	ages := map[string]int{}

此时创建了一个空的map。

创建指定key/value的map
	ages := map[string]int{
		"laowang": 22,
		"laoli":   25,
	}
	//map[laoli:25 laowang:22]

此时初始化了一个指定key/value的map。等价于

	ages := make(map[string]int)
	ages["laowang"] = 22
	ages["laoli"] = 25

当声明了map没有进行初始化时,map的值是nil ,长度为0。

	var mm map[string]string
	fmt.Println(mm == nil) //true
	fmt.Println(len(mm)) //0

map的操作

创建一个map

	ages := make(map[string]int)
	ages["zhangsan"] = 20
	ages["lisi"] = 16
	//map[lisi:16 zhangsan:20]
map对值的操作

map可以直接根据key获取到对应的值

	ages["zhangsan"]++
	ages["unknow"]++
	fmt.Println(ages["zhangsan"]) //21
	fmt.Println(ages["unknow"])  //1


	married := make(map[string]bool)
	married["zhangsan"] = true
	married["lisi"] = false
	fmt.Println(married["zhangsan"]) //true
	fmt.Println(married["xiaolizi"]) // false

根据键获取值,如果找得到对应的value,则返回,如果找不到则返回其value默认值,因此ages["unknow"]++此表达式也是合法的,返回值为1。

那么是如何区分key存在的0值和不存在时的0值的,好在go语言的下标语法将返回两个值;第二个是一个布尔值,用来报告元素是否存在,通常命名为ok。具体写法如下

	if _, ok := mm["key"]; !ok {
		fmt.Println("key is not exist")
	}

注:不允许向nil值的map中存入元素,会导致一个panic异常。

	var mm map[string]string
	mm["zhangsan"] = "haha" //panic: assignment to entry in nil map

map中的元素并不是一个变量,因此不能对map进行取址操作。

	_ := &married["zhangsan"] //cannot take the address of married["zhangsan"]

禁止对map进行取址的原因是map可能随着元素数量的增长而重新分配内存空间,从而导致之前的取址操作无效。

使用delete删除key

使用内置的delete函数可以对map的键值对进行删除,如果找不到对应的key,也不会发生panic。

	delete(ages, "zhangsan")
	fmt.Println(ages) //map[lisi:16]
map的遍历

使用for-range可以对map进行遍历

	ages := make(map[string]int)
	ages["zhangsan"] = 20
	ages["lisi"] = 16
	ages["aqi"] = 31
	for k, v := range ages {
		fmt.Printf("%s %d\n", k, v)
	} 
//zhangsan 21
//lisi 16
//aqi 31

哈希表是无序的,所以遍历的结果也是无序的,如果需要按顺序便利可以先对key进行排序,然后在遍历。具体实现如下:

	var names []string
	for name := range ages {
		names = append(names, name)
	}
	sort.Strings(names)
	for _, name := range names {
		fmt.Printf("%s %d\n", name, ages[name])
	}
//aqi 31
//lisi 16
//zhangsan 21

对map进行遍历,如果不需要值,可以忽略循环的第二个参数。

sort.Strings()函数可以针对string类型的切片进行排序。

在对names 切片进行遍历时,不需要用到索引,可以使用_空白标志符来占位。

补充
  1. map的键必须是可比较的,但一些时候想用slice等类型作为key,那么可以借助辅助函数来完成,将slice转换成string等可比较的类型就可以了。
  2. map中的值并不一定是基础数据类型,比如map的值可以是一个map
	mn := make(map[string]map[string]bool)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值