Go语言--语法基础6--基本数据类型--map类型
Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。
Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。
1、定义声明 Map
可以使用内建函数 make
也可以使用 map
关键字来定义 Map:
/* 声明变量,默认 map 是 nil */
var map_variable map[keyType] valueType
示例:
var a map[int]int
key 和 value 的类型说明
- key 可以是什么类型:golang 中的 map 的 key 可以是很多种类型,比如 bool、数字、string、指针、channel,还可以是只包含前面几个类型的接口、结构体、数组。
注意:slice、map 还有 function 不可以,因为这几个没法用==
来判断。 - value 可以是什么类型:value 的类型和 key 基本一样,通常为:数字(整数、浮点数)、string、map、struct。
map 声明举例
var a map[string]string
var b map[string]int
var c map[int]string
var d map[string] map[string]string
注意:声明是不会分配内存的,初始化需要 make
,分配内存后才能赋值和使用。
/* 使用 make 函数初始化 map */
map_variable = make(map[key] value)
如果不初始化 map,那么就会创建一个 nil map。nil map 不能用来存放键值对。
实例
下面实例演示了创建和读取 map:
package main
import "fmt"
func main() {// 声明 mapvar countryCapitalMap map[string]string/* 创建集合 在使用 map 前,首先要 make 分配数据空间。*/countryCapitalMap = make(map[string]string)/* map 插入 key-value 对,各个国家对应的首都 */// 使用 mapcountryCapitalMap["France"] = "Paris"countryCapitalMap["Italy"] = "Rome"countryCapitalMap["Japan"] = "Tokyo"countryCapitalMap["India"] = "New Delhi"/* 使用 key 输出 map 值 */for country := range countryCapitalMap {fmt.Println("Capital of", country, "is", countryCapitalMap[country])}
}
以上实例运行结果为:
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of India is New Delhi
另外一种 map 声明方式
heroes := map[string]string{"no1": "chengdu", // 注意不能少了“,”号"no2": "beijing","no3": "wuhan",
}
fmt.Println(heroes)
fmt.Println(heroes["no2"])
value 为 map 的案例
比如:我们要存放 3 个学生信息,每个学生有 name 和 sex 信息(思路:map[string] map[string]string
):
stuMap := make(map[string] map[string]string)
stuMap["stu01"] = make(map[string]string)
stuMap["stu01"]["name"] = "zhangsan"
stuMap["stu01"]["age"] = "10岁"
stuMap["stu01"]["addr"] = "xi'an"
stuMap["stu02"] = make(map[string]string)
stuMap["stu02"]["name"] = "lisi"
stuMap["stu02"]["age"] = "9岁"
stuMap["stu02"]["addr"] = "chognqing"
fmt.Println(stuMap)
fmt.Println(stuMap["stu01"])
2、常规操作
1. map 增加和更新
map["key"] = value // 如果 key 还没有,就是增加;如果 key 存在就是修改
示例:
cities := make(map[string]string)
cities["no1"] = "上海"
cities["no2"] = "西安"
cities["no3"] = "天津"
fmt.Println(cities)
// 因为 no3 这个 key 值已经存在,所以下面的就是修改,若无就是增加
cities["no3"] = "天津..."
fmt.Println(cities)
2. map 删除
delete(map, "key")
是用于删除 map 元素的内置函数。如果 key 存在,就删除该 key-value;如果 key 不存在,不操作,也不会报错。
实例:
package main
import "fmt"
func main() { /* 创建 map */countryCapitalMap := map[string] string{"France":"Paris","Italy":"Rome","Japan":"Tokyo","India":"New Delhi",}fmt.Println("原始 map") /* 打印 map */for country := range countryCapitalMap {fmt.Println("Capital of", country, "is", countryCapitalMap[country])}/* 删除元素 */delete(countryCapitalMap, "France");fmt.Println("Entry for France is deleted") fmt.Println("删除元素后 map") /* 打印 map */for country := range countryCapitalMap {fmt.Println("Capital of", country, "is", countryCapitalMap[country])}
}
以上实例运行结果为
原始 map
Capital of France is Paris
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of India is New Delhi
Entry for France is deleted
删除元素后 map
Capital of Italy is Rome
Capital of Japan is Tokyo
Capital of India is New Delhi
注意:如果要全部删除,有两种方式:
- 遍历所有 key,逐一删除。
- 直接
make
一个新空间
cities := make(map[string]string)
fmt.Println(cities)
3. map 查找
Go 语言中有个判断 map 中键是否存在的特殊写法,格式如下:
v, ok := map["key"]
如果 key 存在,ok
为 true
,v
为对应的值;不存在,ok
为 false
,v
为值类型的零值。
示例:
func main() {scoreMap := make(map[string]int)scoreMap["张三"] = 90scoreMap["小明"] = 100// 演示 map 查找v, ok := scoreMap["张三"]if ok {fmt.Println(v)} else {fmt.Println("查无此人")}
}
4. map 的遍历
Go 语言中使用 for range
遍历 map。
常规遍历方式
func main() {scoreMap := make(map[string]int)scoreMap["张三"] = 90scoreMap["小明"] = 100scoreMap["王五"] = 60// 常规遍历方式 for k, v := range scoreMap {fmt.Println(k, v) // 输出键值对}
}
只遍历 key 或 value
func main() {scoreMap := make(map[string]int)scoreMap["张三"] = 90scoreMap["小明"] = 100scoreMap["王五"] = 60// 只输出键for k := range scoreMap {fmt.Println(k)}// 只输出值for _, v := range scoreMap {fmt.Println(v)}
}
注意:遍历 map 时的元素顺序与添加键值对的顺序无关。
复杂 map 遍历
for k1, v1 := range stuMap {fmt.Println("k1 =", k1)for k2, v2 := range v1 {fmt.Printf("\t k2 =%v v2=%v \n", k2, v2)}fmt.Println()
}
按照指定顺序遍历 map
import ("fmt" "math/rand""sort""time"
)func main() {rand.Seed(time.Now().UnixNano()) // 初始化随机数种子var scoreMap = make(map[string]int, 200) // 定义并声明一个容量为200个 string-int 的 mapfor i := 0; i < 100; i++ { // i 从 0 - 99key := fmt.Sprintf("stu%02d", i) // 生成 stu 开头的字符串 // %d 数字 %2d 两位数字 %02d 不够两位做 0 填充// stu00 stu01 stu02 ... stu99value := rand.Intn(100) // 生成 0~99 的随机整数,rand 随机数生成函数scoreMap[key] = value // stu00 = 0~99 之间的随机数赋值}// 取出 map 中的所有 key 存入切片 keysvar keys = make([]string, 0, 200) // 定义并生成一个 200 个容量的切片,切片名称是 keysfor key := range scoreMap {keys = append(keys, key)}// 对切片进行排序sort.Strings(keys)// 按照排序后的 key 遍历 mapfor _, key := range keys {fmt.Println(key, scoreMap[key])}
}
课堂练习
- 定义一个 id 和姓名的 map 来存储学生信息,并可以遍历输出。
- 定义一个姓名和班级的 map 类存储学生的成绩信息,并可以完成基本的增删改查。