1. 前言
Map的数据结构是key-value,可通过key来快速检索数据,类似其它语言中的字典、hash等,由于Map是使用hash表实现的,所以它也是无序的,不能决定它返回的顺序。
2. Map定义
map 是引用类型的,使用时需要先声明
var mapname map[keytype]valuetype
map 未初始化值是 nil, 可使用make()来初始化
make(map[KeyType]ValueType, [cap])
map可根据新增的键值对来动态的伸缩容量,无最大限制,cap是非必须的参数,但是我们在初始化时一般会给它指定一个合适的容量。
示例:
package main
import "fmt"
func main() {
price := make(map[string]int, 8)
price["apple"] = 8
price["grape"] = 18
fmt.Println(price)
// 也可声明时直接赋值
fruits := map[string]string{
"apple": "苹果",
"grape": "葡萄",
}
fmt.Println(fruits)
fmt.Println(fruits["grape"],":",price["grape"])
}
输出:
map[apple:8 grape:18]
map[apple:苹果 grape:葡萄]
葡萄 : 18
3. 判断键值对是否存在
在上述代码里,我们直接Println出fruits["grape"],要是grape键值对不存在的话fruits["grape"]就会返回空值,这样子我们就不能区分它是不存在还是对应的值就是空。
为了解决这个问题,go中有个判断map中键是否存在的特殊写法,格式如下:
value, ok := map[key]
ok 为bool类型,key存在ok为true;不存在ok为false,value为空值
示例:
package main
import "fmt"
func main() {
// 也可声明时直接赋值
fruits := map[string]string{
"apple": "苹果",
"grape": "葡萄",
}
v, ok := fruits["apple"]
if ok {
fmt.Println(v)
}
_, ok = fruits["apple123"]
if !ok {
fmt.Println("apple123不存在")
}
}
输出:
苹果
apple123不存在
4. 键值对删除
可使用delete()函数删除map中的一组键值对,格式如下:
delete(map, key)
key不在map时,delete操作不会产生错误。
示例:
package main
import "fmt"
func main() {
// 也可声明时直接赋值
fruits := map[string]string{
"apple": "苹果",
"grape": "葡萄",
}
fmt.Println("原始:", fruits)
// 将apple:苹果从fruits中删除
delete(fruits, "apple")
fmt.Println("删除后:", fruits)
// 删除不存在的键值对,不会报错
delete(fruits, "apple123")
}
输出:
原始: map[apple:苹果 grape:葡萄]
删除后: map[grape:葡萄]
5. map遍历
和数组切片一样,map也可以使用循环
示例:
package main
import (
"fmt"
)
func main() {
var grade = make(map[string]int, 5)
for i := 0; i < 5; i++ {
key := fmt.Sprintf("map-%02d", i)
grade[key] = i
}
//取出map中的所有key存入切片keys
for key, value := range grade {
fmt.Printf("%v : %d\n", key, value)
}
}
输出:
map-02 : 2
map-03 : 3
map-04 : 4
map-00 : 0
map-01 : 1
6. map排序
可以看到上面 map遍历输出的结果是乱序的,这也证实了map是无序的,那要想map有序输出,也是有办法的,借助切片对map的键值去排序后循环输出即可,代码如下:
package main
import (
"fmt"
"sort"
)
func main() {
var grade = make(map[string]int, 5)
for i := 0; i < 5; i++ {
key := fmt.Sprintf("map-%02d", i)
grade[key] = i
}
// 取出grade中的所有key
var keys = make([]string, 0, len(grade))
for key := range grade {
keys = append(keys, key)
}
// 对切片keys进行排序
sort.Strings(keys)
// 按照排序后的key遍历grade
for _, key := range keys {
fmt.Println(key, grade[key])
}
}
输出:
map-00 0
map-01 1
map-02 2
map-03 3
map-04 4
7. map类型的切片
获取一个map 类型的切片,需要使用两次make(),第一次初始化切片,第二次初始化切片中每个map元素
示例:
package main
import (
"fmt"
)
func main() {
fmt.Println("对切片进行初始化")
var fruits = make([]map[string]string, 3)
for key, value := range fruits {
fmt.Printf("key:%d value:%v\n", key, value)
}
fmt.Println("对切片中的map元素进行初始化")
fruits[0] = make(map[string]string, 10)
fruits[0]["apple"] = "苹果"
fruits[0]["grape"] = "葡萄"
fruits[0]["banana"] = "香蕉"
for key, value := range fruits {
fmt.Printf("key:%d value:%v\n", key, value)
}
}
输出:
对切片进行初始化
key:0 value:map[]
key:1 value:map[]
key:2 value:map[]
对切片中的map元素进行初始化
key:0 value:map[apple:苹果 banana:香蕉 grape:葡萄]
key:1 value:map[]
key:2 value:map[]
8. 切片类型的map
package main
import (
"fmt"
)
func main() {
fmt.Println("对map进行初始化")
var fruits = make(map[string][]string, 3)
fmt.Println(fruits)
fmt.Println("对切片进行初始化")
slice := make([]string, 0, 3)
fruits["常见水果"] = append(slice, "苹果", "葡萄", "香蕉")
fmt.Println(fruits)
}
输出:
对map进行初始化
map[]
对切片进行初始化
map[常见水果:[苹果 葡萄 香蕉]]