目录
- Map声明
- Map添加元素
- Map删除元素
- Map元素访问
- Map遍历
- Map排序
- 如何按Key排序Map
- 如何按Value排序Map
Map声明
- 声明后添加元素
m := map[string]int{}
m["a"] = 1
- 声明并初始化
m := map[string]int{"a":1, "b":2, "c":3}
- make创建
m := make(map[string]int, 10/*Initial Capacity*/)
上一篇文章我们使用make创建了切片,同样make也可以创建Map,不同的是不需要初始化len,原因是Map无法设置元素默认值,而切片可以根据数据的类型设置默认值,比如切片的元素为int类型,默认值则为0.
使用make通过预先设置capacity的方式创建,避免了capacity在自增的过程的分配新的内存空间和内存拷贝,可以减少内存消耗,提高性能。
接下来我代码演示下Map的创建:
func TestInitMap(t *testing.T) {
m1 := map[int]int{1: 1, 2: 2, 3: 3}
t.Log(m1, len(m1))
m2 := map[int]int{}
t.Log(m2, len(m2))
m2[0] = 0
m2[5] = 5
t.Log(m2, len(m2))
m3 := make(map[string]string, 10)
// 不能查看Map的Capacity,否者会报错:Invalid argument for cap
//t.Log(m3, len(m3), cap(m3))
t.Log(m3, len(m3))
m3["a"] = "1"
m3["b"] = "2"
m3["c"] = "3"
m3["d"] = "4"
t.Log(m3, len(m3))
}
Map添加元素
m[Key] = Value
Map删除元素
delete(m, Key)
例如:
func TestDeleteKey(t *testing.T) {
m := map[int]int{}
t.Log(m[1])
m[2] = 0
t.Log(m[2])
printKey3Exists(&m, t)
m[3] = 0
printKey3Exists(&m, t)
delete(m, 3)
printKey3Exists(&m, t)
}
func printKey3Exists(m *map[int]int, t *testing.T) {
t.Log(m)
if v, ok := (*m)[3]; ok {
t.Logf("key 3's value is %d", v)
} else {
t.Log("key 3 is not existing.")
}
}
Map元素访问
Map元素的访问其实和其他编程语言没什么区别,都是通过Key来得到Value。
t.Log(m3["d"])
不同的是,当访问一个不存在的Key时,Value为类型的默认值,这样虽然可以避免在取一个不存在的Key时,不会出现异常,但是不能知道这个Key到底存不存在。
Go当然考虑到了这一点,即使用10《Go语言入门》循环和条件中讲过的条件语句特殊写法来实现Key是否存在的判断。
func TestAccessNotExistingKey(t *testing.T) {
m1 := map[int]int{}
t.Log(m1[0]) // 0这个key不存在,取int的默认值0为value
m1[2] = 0
t.Log(m1[2])
m2 := map[string]string{}
t.Log(m2["a"]) // a这个key不存在,取string的默认值空字符串为value
m2["a"] = "1"
t.Log(m2["a"])
// 这样虽然可以避免在取一个不存在的key时,不会出现异常,但是不能知道这个key到底存不存在
key := 3
m1[key] = 31
if v, exists := m1[3]; exists {
t.Logf("Key %d's value is %d", key, v)
} else {
t.Logf("Key %d is not existing", key)
}
}
Map遍历
和数组、切片的遍历是一样的。
这里我们随便回忆下数组和切片的遍历。
需要注意的是:map底成是通过hash来指定存储位置的,所以遍历出来的元素不是有序的。
func TestTravelMap(t *testing.T) {
t.Log("Map遍历")
m3 := make(map[string]string, 10)
t.Log(reflect.TypeOf(m3))
m3["a"] = "1"
m3["b"] = "2"
m3["c"] = "3"
m3["d"] = "4"
t.Log(m3)
for key, value := range m3 {
t.Log(key, value)
}
t.Log("Array遍历")
array := [...]string{"a", "b", "c"}
t.Log(reflect.TypeOf(array))
for index, element := range array {
t.Log(index, element)
}
t.Log("Slice遍历")
slice := []string{"a", "b", "c"}
t.Log(reflect.TypeOf(slice))
for index, element := range slice {
t.Log(index, element)
}
}
Map排序
如何按Key排序Map
我这里写一种方法,通过将Key存储到slice中,然后给slice排序,再遍历slice即可。
func TestSortByKey(t *testing.T) {
m1 := map[string]int{"aa": 1, "zz": 2, "bb": 3, "yy": 4, "cc": 5, "xx": 6}
s1 := make([]string, 0, len(m1))
for k, _ := range m1 {
s1 = append(s1, k)
}
sort.Strings(s1)
for _, k := range s1 {
t.Log(k, m1[k])
}
}
如何按Value排序Map
很容易理解的,直接看代码吧。
func TestSortByValue(t *testing.T) {
m1 := map[string]int{"aa": 3, "zz": 1, "bb": 5, "yy": 2, "cc": 4, "xx": 6}
valueSlice := make([]int, 0, len(m1))
for _, value := range m1 {
valueSlice = append(valueSlice, value)
}
sort.Ints(valueSlice)
for _, element := range valueSlice {
for key, value := range m1 {
if element == value {
t.Log(key, value)
}
}
}
}