golang中的map

x33g5p2x  于2021-12-30 转载在 Go  
字(1.6k)|赞(0)|评价(0)|浏览(304)

在golang中,map是散列表的引用,也就是说它是引用类型,像指针那样。

map的类型是map[K]V,所有元素的key都K类型,所有元素的value都是V类型。

初始化map

m := make(map[string]int) 	// 方式一
m := map[string]int{}			// 方式二

避免对零值(未初始化)的map设置kv。

var ages map[string]int
ages["tom"] = 12				// 异常

var ages := map[string]int{}
ages["tom"] = 12				// 正常

赋值

m["foo"] = 1
m["bar"] = 2

// 初始化带赋值
m2 := map[string]int{
    "foo": 1,
    "bar": 2,		//注意这个标点符号,是不能少的Ï
}

访问元素、删除元素

通过key来访问元素,通过内置的delete函数,根据key来删除元素

m["hello"] = 3
fmt.Println(m["hello"])		// 3
delete(m, "hello")
fmt.Println(m["hello"])		// 0
fmt.Println(m["nothing"])	// 0

访问不存在的key,也不会抛出异常,而是会返回map value的零值。

fmt.Println(m["nothing"])	// 0
m["nothing"]++
fmt.Println(m["nothing"])	//	1

判断key是否存在

既然不管key存在不存在,map都会返回一个值,那如何区分map里到底是包含了个本来就是空值的key还是根本没有这个key呢?

其实通过key来访问value的话,返回两个值,第一个值是元素的value,第二个值就是这个key是否存在。

if value, ok := m["nothing-2"]; ok {
    fmt.Println("存在,value = " + strconv.Itoa(value))
} else {
    fmt.Println("不存在")
}

元素的指针

map的元素不是一个变量,所以无法获取它的地址, &m["foo"]无法通过编译,其中一个原因是随着map的增长,它会重新散列已有元素,这样的话原地址就无法保证了。

元素的遍历

for k, v := range m {
    fmt.Printf("%s = %d\n", k, v)
}

map是无序的,如果向按照key的字典顺序来遍历,则需要借助数组和sort

names := make([]string, 0, len(m))
for k := range m {
    names = append(names, k)
}

sort.Strings(names)

for _, name := range names {
    fmt.Printf("%s = %d\n", name, m[name])
}

map的可比较性

和slice一样,map不可比较。

如何用map充当set

使用一个map[T]bool类型的map来充当set,往"set"里增加元素时,m[key]=true,然后通过判断m[key]是否true来判断"set"中是否存在key。

如何应付特殊的key

map中的key必须是可比较的,并且不建议使用float和double。如果你想用double、slice等作为key的话,可以参考java的做法,自己实现一个确定的hashCode()方法,编码出来一个string或int。

相关文章