map概述
哈希表是一种巧妙并且使用的数据结构。它是一个无序的key-value
对的集合,其中所有的key都是不同的,然后通过给定的key可以在常数时间复杂度内检索、更新或删除对应的value。
Golang中,一个map就是一个哈希表的引用,又称为字段或者关联数组。类似其他编程语言的集合,在编程中是经常使用到。
map的声明
基本语法
var map 变量名 map[keytype]valuetype
key的类型
Golang中的map的key可以是很多种类型,比如bool,数字,string,指针,channel,还可以是接口,结构体,数组。key对应的类型必须支持
==
比较运算符的数据类型,所以map可以通过测试key是否相等来判断是否已经存在。通常key为int、string。
注意:slice,map还有function不可以作为key,因为这几个没法用
==
来判断。valuetype的类型
valuetype的类型没有任何的限制
通常为:数字(整数,浮点数),string,map,struct。
map声明举例
var a map[string]string var a map[string]int var a map[int]string var a map[string]map[string]string
注意:声明是不会分配内存的,初始化需要使用make,分配内存后才能赋值和使用。内建函数make分配并初始化一个类型为切片、映射、或通道的对象。
map声明案例演示:
func main(){ var a map[string]string a = make(map[string]string, 10) //使用make函数给map分配数据空间 a["no1"] = "tom" a["no2"] = "jerry" a["no3"] = "jack" a["no1"] = "alice" fmt.Println(a) }
对上面代码的说明:
map在使用前一定要make
map的key是不能重复的。如果重复了,则以最后这个key-value为准
map的value是可以相同的
map的key-value是无序的
map的使用
方式一:
var a map[string]string //在使用map前,需要先make,make的作用是给map分配数据空间 a = make(map[string]string, 10) a["no1"] = "tom" a["no2"] = "jerry" a["no3"] = "jack" a["no1"] = "alice" fmt.Println(a)
方式二:
cities := make(map[string]string) cities["no1"] = "北京" cities["no2"] = "天津" cities["no3"] = "上海" fmt.Println(cities)
方式三:
heroes := map[string]string{ "heroes1" : "钢铁侠" "heroes2" : "蜘蛛侠" "heroes3" : "绿巨人" } heroes["heroes4"] = "黑寡妇" fmt.Println("heroes=", heroes)
案例演示:
案例需求:存放三个学生的信息,每个学生有name和sex信息
students := make(map[string]map[string]string, 3) //对于map要先使用make声明,students中的value也是map,所以对于每个key对应的值都需要map students["stu01"] = make(map[string]string, 2) students["stu01"]["name"] = "tom" students["stu01"]["sex"] = "男" students["stu02"] = make(map[string]string, 2) students["stu02"]["name"] = "mary" students["stu02"]["sex"] = "女" fmt.Println(students) fmt.Println(students["stu01"]) fmt.Println(students["stu01"]["name"])
map的增删改查操作
map增加和更新
map["key"] = value //如果key还没有,就是增加,如果key存在就是修改
删除
删除map中的一个键值对,使用内置函数delete
。使用方法:delete(map, "key")
,如果key存在,就删除key-value,如果不存在,不操作,但也不会报错。
cities := make(map[string]string) cities["no1"] = "北京" cities["no2"] = "天津" cities["no3"] = "上海" fmt.Println(cities) //使用delete内置函数删除cities中的键值对 delete(cities, "no1") fmt.Println(cities) delete(cities, "no4") fmt.Println(cities)
在Golang中没有一下删除整个map中的key的函数。这时可以遍历一下key逐个删除,或者map = make(...)
,make一个新的,让原来的成为垃圾,被gc回收。
//方法一:使用make,开辟一个新的map空间 cities = make(map[string]string) fmt.Println(cities) //方法二:遍历key,逐个删除 for key, _ := range cities { delete(cities, cities[key]) }
查找
map的查找还是通过key来进行查找,我们可以封装一个函数,参数为key和map,返回值为bool类型;如果找到返回true,否则返回false。代码如下:
func findRes(key string, m map[string]string) bool { _, ok := m[key] // 判断某个键是否存在 if ok { return true } else { return false } } func main() { cities := make(map[string]string) cities["no1"] = "北京" cities["no2"] = "天津" cities["no3"] = "上海" fmt.Println(cities) fmt.Println(findRes("no1", cities)) fmt.Println(findRes("no4", cities)) }
遍历
map的遍历使用使用for-range的结构遍历
func main() { cities := make(map[string]string) cities["no1"] = "北京" cities["no2"] = "天津" cities["no3"] = "上海" fmt.Println(cities) for k, v := range cities { fmt.Printf("k=%v v=%v\n", k, v) } //变量map的map students := make(map[string]map[string]string, 3) //对于map要先使用make声明,students中的value也是map,所以对于每个key对应的值都需要map students["stu01"] = make(map[string]string, 2) students["stu01"]["name"] = "tom" students["stu01"]["sex"] = "男" students["stu02"] = make(map[string]string, 2) students["stu02"]["name"] = "mary" students["stu02"]["sex"] = "女" for key1, value1 := range students { fmt.Println("key1=", key1) for key2, value2 := range value1 { fmt.Printf("\tkey2=%v value2=%v\n", key2, value2) } } }
使用len()
内建函数可以返回map的长度:
func main() { cities := make(map[string]string) cities["no1"] = "北京" cities["no2"] = "天津" cities["no3"] = "上海" fmt.Println(cities) //变量map的map students := make(map[string]map[string]string, 3) //对于map要先使用make声明,students中的value也是map,所以对于每个key对应的值都需要map students["stu01"] = make(map[string]string, 2) students["stu01"]["name"] = "tom" students["stu01"]["sex"] = "男" students["stu02"] = make(map[string]string, 2) students["stu02"]["name"] = "mary" students["stu02"]["sex"] = "女" fmt.Println(len(students)) //2 fmt.Println(len(cities)) //3 }
map切片
基本介绍
切片的数据类型如果是map,则称为slice of map(map切片),这样map的个数就可以动态变化。
map切片的使用
案例演示:
案例需求:使用一个map来记录学生的信息name和age,并且学生的个数可以动态增加
func main() { //声明一个students的map切片 var students []map[string]string students = make([]map[string]string, 2) //先存放两个学生 if students[0] == nil { students[0] = make(map[string]string, 2) students[0]["name"] = "tom" students[0]["age"] = "24" } if students[1] == nil { students[1] = make(map[string]string, 2) students[1]["name"] = "mary" students[1]["age"] = "20" } //越界panic: runtime error: index out of range [2] with length 2 //if students[2] == nil { // students[2] = make(map[string]string, 2) // students[2]["name"] = "jerry" // students[2]["age"] = "20" //} //使用append函数动态的增加students student := map[string]string { "name" : "jerry", "age" : "20", } students = append(students, student) fmt.Println(students) //[map[age:24 name:tom] map[age:20 name:mary] map[age:20 name:jerry]] }
map排序
基本介绍
Golang中没有一个专门的方法或者函数针对map的key进行排序。Golang中的map默认是无序的,注意也不是按照添加的顺序存放的,每次遍历,得到的输出可能不一样。
map排序方法:先将key进行排序,然后根据key值遍历输出即可
map排序演示
func main() { rand.Seed(time.Now().UnixNano()) //初始化随机种子 // 声明一个scoreMap用来存学生的成绩 var scoreMap = make(map[string]int, 200) for i := 0; i < 100; i++ { key := fmt.Sprintf("stu%02d", i) //生成stu开头的字符串 scoreMap[key] = rand.Intn(100) //生成0-100之间的随机数作为学生的成绩 } var keys = make([]string, 0, 100) //取出scoreMap中的key存储到[]key切片中 for key := range scoreMap { keys = append(keys, key) } //对切片进行排序 sort.Strings(keys) //使用排序好的key对scoreMap进行遍历 for _, k := range keys { fmt.Println(k, scoreMap[k]) } }
map使用细节
map是引用类型,遵守引用类型传递的机制,在一个函数接收map,修改之,则会修改原来的map
map的容量达到后,再想map增加元素,会自动扩容,并不会发生panic,也就是说map能动态的增长
key-value
map的value也经常使用struct类型,更适合管理复杂的数据
type Stu struct { name string age int } func main() { // 使用map来存储Stu结构体 // 学生的学号作为map的key,因为学号唯一,学生的姓名和年龄作为Stu结构体的字段 var stuMap = make(map[string]Stu, 10) stuMap["no1"] = Stu{"tom", 19} stuMap["no2"] = Stu{"jerry", 20} fmt.Println(stuMap) // map[no1:{tom 19} no2:{jerry 20}] }
练习
- 使用
map[string]map[string]string
的map类型,key表示用户名,是唯一的,不可以重复;如果这个用户名存在,就将其密码修改成"666666",如果不存在就增加这个用户的信息(nickname和密码pwd) - 统计一个字符串中每个单词出现的次数。比如:"how are you are you right",how=1,are=2,you=2,right=1
- 观察下面代码,写出最终的打印结果
func main() { type Map map[string][]int m := make(Map) s := []int{1, 2} s = append(s, 3) fmt.Printf("%+v\n", s) m["q1mi"] = s s = append(s[:1], s[2:]...) fmt.Printf("%+v\n", s) fmt.Printf("%+v\n", m["q1mi"]) }
来源:https://www.cnblogs.com/dabric/p/12337500.html