作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.映射(map)定义
1.映射(map)概述
映射(map)是一种无序的基于key-value的数据结构,Go语言中的map是引用类型,必须初始化才能使用。
Go语言中提供的映射关系容器为map,其内部使用散列表(hash)实现。
映射(map)是Go语言中内置的一种类型,它将键值相关联,我们可以通过key来获取对应的value,有点类似于其他语言的集合。
映射(map)的特点:
- 1.map结合在使用前一定要make;
- 2.map的key-value是无序的;
- 3.key是不可以重复的,如果遇到重复,后一个value会替换前一个value;
- 4.不同的key,其value是可以重复的;
2.map的语法格式
Go语言中map的定义语法如下:
map[KeyType]ValueType
map类型的变量默认初始值为nil,需要使用make()函数来分配内存。语法为:
make(map[KeyType]ValueType, [cap])
相关字段说明:
KeyType:
表示键的类型。
ValueType:
表示键对应的值的类型。
cap
map的容量,该参数可选,但建议在初始化map的时候就为其指定一个合适的容量。
温馨提示:
- 1.key,value的类型包括但不限于bool,数值型,string,指针,chan,还可以只包含前面几个类型的接口,结构体,数组等;
- 2.key部分通常为int,string类型,value通常为数字(整数,浮点数),string,map,结构体;
- 3.key部分不可以是slice,map,function等类型;
3.map的三种创建方式
3.1 先声明在make
package main
import "fmt"
func main() {
// 1.声明map变量,但并没有分配堆内存空间
var dongMan map[int]string
// 2.必须通过make函数进行初始化,才会在堆内存中分配空间
dongMan = make(map[int]string, 5) // map可以存放5个键值对,但实际存储超过5个依旧是可以的
// 3.将键值对存储map中
dongMan[20230925] = "《仙逆》"
dongMan[20200725] = "《凡人修仙传》"
dongMan[20201129] = "《吞噬星空》"
dongMan[20220129] = "《永生》"
dongMan[20140731] = "《画江湖之不良人》"
dongMan[20131214] = "《师兄啊师兄》"
dongMan[20021003] = "《火影忍者》"
dongMan[20080517] = "《葫芦兄弟》"
dongMan[19990723] = "《西游记》"
// 4.输出集合
fmt.Printf("dongman = %v\n", dongMan)
}
3.2 直接使用make初始化map
package main
import "fmt"
func main() {
// 1.初始化map类型
language := make(map[string]uint16)
// 2.赋值
language["C"] = 1972
language["C++"] = 1983
language["Python"] = 1989
language["JAVA"] = 1995
language["Golang"] = 2007
language["Scala"] = 2003
language["Ruby"] = 1993
language["Php"] = 2004
language["HTML"] = 1989
language["CSS"] = 1994
language["JavaScript"] = 1995
// 3.查看map数据
fmt.Printf("language = [%v]\n", language)
}
3.3 直接赋值初始化map
package main
import "fmt"
func main() {
dbInfo := map[string]string{
"Username": "jasonyin2020",
"Password": "yinzhengjie",
"DbHost": "www.yinzhengjie.com",
"DbPort": "3306",
"DbName": "wordpress",
}
fmt.Printf("userInfo = %v\n", dbInfo)
}
二.map基本使用
1.map的增删改查
package main
import "fmt"
func main() {
// 1.定义map
constellation := make(map[string]string)
// 2.增加
constellation["金牛座"] = "土象星座: 0420-0520"
constellation["处女座"] = "土象星座: 0823-0922"
constellation["摩羯座"] = "土象星座: 1222-0119"
// 3.修改
constellation["狮子座"] = "火象星座: 0723-0822"
fmt.Printf("删除前: len(constellation) = %d\n", len(constellation))
// 4.删除指定map的key,若key不存在,并不会报错
delete(constellation, "摩羯座")
fmt.Printf("删除后: len(constellation) = %d\n", len(constellation))
// 5.查找,判断某个键是否存在
value, ok := constellation["狮子座"]
if ok {
fmt.Printf("狮子座的出生日期: %v\n", value)
} else {
fmt.Println("查无此人")
}
fmt.Printf("星座: %v\n", constellation)
}
2.map的遍历
package main
import "fmt"
func main() {
constellation := make(map[string]string)
constellation["金牛座"] = "土象星座: 0420-0520"
constellation["处女座"] = "土象星座: 0823-0922"
constellation["摩羯座"] = "土象星座: 1222-0119"
constellation["狮子座"] = "火象星座: 0723-0822"
// Go语言中使用for range遍历map,遍历map时的元素顺序与添加键值对的顺序无关。
for key, value := range constellation {
fmt.Printf("key = %v, value = %v\n", key, value)
}
fmt.Println("----- 我是分割线 -----")
// 但我们只想遍历key的时候,仅需使用一个参数来接收哟~
for k := range constellation {
fmt.Printf("key = %v\n", k)
}
}
3.嵌套map遍历
package main
import "fmt"
func main() {
dongMan := make(map[string]map[int]string)
// 由于map的值为map类型,因此我们需要对值先进行make再使用,否则会抛出异常
dongMan["腾讯视频"] = make(map[int]string, 3)
dongMan["腾讯视频"][20230925] = "《仙逆》"
dongMan["腾讯视频"][20201129] = "《吞噬星空》"
dongMan["腾讯视频"][20140731] = "《画江湖之不良人》"
// 由于map的值为map类型,因此我们需要对值先进行make再使用,否则会抛出异常
dongMan["B站"] = make(map[int]string, 2)
dongMan["B站"][20200725] = "《凡人修仙传》"
dongMan["B站"][20220129] = "《永生》"
// 由于map的值为map类型,因此我们需要对值先进行make再使用,否则会抛出异常
dongMan["优酷"] = make(map[int]string, 2)
dongMan["优酷"][20131214] = "《师兄啊师兄》"
dongMan["优酷"][20021003] = "《火影忍者》"
for k1, v1 := range dongMan {
fmt.Printf("k1 = %v\n", k1)
for k2, v2 := range v1 {
fmt.Printf("[%v]动漫的发行时间是: [%d]\n", v2, k2)
}
}
}
4.元素为map类型的切片
package main
import (
"fmt"
)
func main() {
// 定义一个长度为3的切片
var mapSlice = make([]map[string]string, 3)
// 对切片的各个元素进行遍历
for index, value := range mapSlice {
fmt.Printf("index: %d value: %v\n", index, value)
}
fmt.Println("----- 分割线 -----")
// 对切片中的第一个(索引下标为0)map元素进行初始化
mapSlice[0] = make(map[string]string, 10)
mapSlice[0]["name"] = "Jason Yin"
mapSlice[0]["password"] = "123456"
mapSlice[0]["address"] = "北京市昌平区沙河镇"
for index, value := range mapSlice {
fmt.Printf("index: %d value: %v\n", index, value)
}
}
5.值为切片类型的map
package main
import (
"fmt"
)
func main() {
// 定义一个map类型
var sliceMap = make(map[string][]string, 3)
key := "中国"
value, ok := sliceMap[key]
if !ok {
// 如果key="中国"不存在,则对其值进行初始化为一个容量为2的字符串切片。
value = make([]string, 0, 2)
}
// 紧接着,由于切片是引用类型,我们往该切片中添加2个字符串类型元素
value = append(value, "北京", "上海")
fmt.Printf("地址: %p, 数据: %v, 长度: %d, 容量: %d\n", value, value, len(value), cap(value))
// 往切片追加元素,原有的切片底层数组将存不下,于是会产生新的底层数组哟~
value = append(value, "深圳", "石家庄", "西安")
fmt.Printf("地址: %p, 数据: %v, 长度: %d, 容量: %d\n", value, value, len(value), cap(value))
// 注意,此处我们切片进行赋值给map的key。
sliceMap[key] = value
fmt.Println(sliceMap)
}
三.练习题
1.写一个程序,统计一个字符串中每个单词出现的次数
package main
import (
"fmt"
"strings"
)
func main() {
// 统计一个字符串中每个单词出现的次数
s1 := "I love you , and you ?"
// 将字符串按照空格子串进行切割
res := strings.Split(s1, " ")
// 初始化用于单词统计的map
var wordCount = make(map[string]int, 10)
// 如果单词不存在,则将其值设置为1,若存在,则将其值进行加一操作。
for _, value := range res {
_, ok := wordCount[value]
if !ok {
wordCount[value] = 1
} else {
wordCount[value]++
}
}
// 遍历字典
for k, v := range wordCount {
fmt.Printf("%s: %d\n", k, v)
}
}
2.看代码手写结果
package main
import (
"fmt"
)
func main() {
// 自定义一个Map类型,底层对应的是一个map类型哟~
type Map map[string][]int
// 初始化咱们的自定义类型
m := make(Map)
s1 := []int{100, 200}
s1 = append(s1, 300)
fmt.Printf("s1 = %+v\n", s1)
m["JasonYin"] = s1
s1 = append(s1[:1], s1[2:]...)
fmt.Printf("s1 = %+v\n", s1)
fmt.Printf("m['JasonYn'] = %+v\n", m["JasonYin"])
}