Go语言学习之map
1.map的基本介绍
map是 key-value数据结构,又称为字段或者关联数组,类似JAVA的集合
在编程中经常使用到
2.map的声明
1.语法: var map 变量名 map[keytype]valuetype
》key可以是什么类型
Golang中的map的key可以是多种类型,比如:bool,数字,String,指针,Channel.还可以包含前面几个类型的:接口,结构体,数组
通常key 为 int,string
注意:slice,map还有function不可以,因为这几个没法用==来判断
》valuetype可以是什么类型
valuetype的类型和key基本一样
通常为:数字(整数,浮点数),string,map,struct
2.map声明实例
var a map[string]string
var a map[string]int
var a map[int]string
var a map[string]map[string]string
注意:声明是不会分配内存的,初始化需要make,分配内存后才能赋值和使用
package main
import "fmt"
func main() {
//map的声明和注意事项
var a map[string]string
//在使用map前,需要先make,make的作用就是给map分配数据空间
a=make(map[string]string,10)
a["no1"]="李白"
a["no2"]="杜甫"
a["no3"]="苏轼"
a["no4"]="陆游"
fmt.Println(a)
}
代码说明:
》map在使用前一定要make
》map的key是不能重复的,如果重复了,则以最后这个key-value为准
》map的value是可以相同的
》map的key-value是无序
》make内置函数数目
func make
func make(Type,size Integer Type)Type
内置函数make分配并初始化一个类型为切片,映射,或通道的对象,其第一个实参为类型,而非值,make的返回类型与其参数不同,而非指向它的指针,其具体结果取决于具体的类型
切片:size指定了其长度,该切片的容量等于其长度。切片支持第二个整数实参可用来指定不同的容量;它必须不小于其长度,因此make([]int,0,10)会分配一个长度为0,容量为10的切片
映射:初始化分配的创建取决于size,但产生的映射长度为0,size可以省略
这种情况下就会分配一个小的起始大小
通道:通道的缓存根据指定的缓存容量初始化,若size为零或被省略,该通道即为无缓存的
3.map的使用
方式1:
//map的声明和注意事项
var a map[string]string
//在使用map前,需要先make,make的作用就是给map分配数据空间
a=make(map[string]string,10)
a["no1"]="李白"
a["no2"]="杜甫"
a["no3"]="苏轼"
a["no4"]="陆游"
fmt.Println(a)
方式2:
//第二种方式
city:=make(map[string]string)
city["no1"]="beijing"
city["no2"]="shanghai"
city["no3"]="shenzhen"
fmt.Println(city)
方式3:
//第三种方式
meinv:=map[string]string{
"mm01":"西施"
“mm02":"昭君"
“mm03":"貂蝉"
}
meinv["mm03"]="玉环"
map使用的课堂案例:
演示一个key-value的value 是map的案例
比如:我们要存放3个学生信息,每个学生有name和sex信息
思路:map[string]map[string]string
代码:
package main
import "fmt"
func main() {
stuMap:=make(map[string]map[string]string)
stuMap["stu01"]=make(map[string]string,3)
stuMap["stu01"]["name"]="tom"
stuMap["stu01"]["sex"]="男"
stuMap["stu01"]["address"]="北京"
stuMap["stu02"]=make(map[string]string,3)
stuMap["stu02"]["name"]="alex"
stuMap["stu02"]["sex"]="男"
stuMap["stu02"]["address"]="广西"
fmt.Println(stuMap)
fmt.Println(stuMap["stu02"])
fmt.Println(stuMap["stu02"]["name"])
}
4.map的增删改查操作
map增加和更新
map[“key”]=value//如果key还没有,就是增加,如果key存在就是修改
cities:=make(map[string]string)
cities["no1"]="北京"
cities["no2"]="上海"
cities["no3"]="天津"
fmt.Println(cities)
cities["no3"]="newYork"
fmt.Println(cities)
map删除
说明:
delete(map,“key”),delete是一个内置函数,如果key存在,就删除该key-value,
如果Key不存在,不操作,但是也不会报错
func delete
func delete(m map[Type]Type1,key Type)
内建函数delete按照指定的键将元素从映射中删除。若m为nil或无此元素,delete不进行操作
//演示删除
delete(cities,"no1")
fmt.Println(cities)
//delete指定的key不存在时,删除不会操作,也不会报错
delete(cities,"no5")
fmt.Println(cities)
》细节说明:
如果我们要删除Map的所有key,没有一个专门的方法一次删除,可以遍历一下key,逐个删除 或者 map=make(…),make一个新的,让原来的成为垃圾,被gc回收
cities=make(map[string]string)
fmt.Println(cities)
》map查找
//ok是一个布尔值,如果有就返回true,没有就返回false
val,ok:=cities["no2"]
if ok{
fmt.Printf("有no2 key值为 %v \n",val)
}else {
fmt.Printf("没有No2 key\n")
}
5.map的遍历
案例演示相对复杂的map遍历,该map的value 又是一个map
说明:map的遍历使用for-range结构遍历
package main
import "fmt"
func main() {
//使用for -range遍历map
cities:=make(map[string]string)
cities["no1"]="北京"
cities["no2"]="上海"
cities["no3"]="天津"
for k,v:=range cities{
fmt.Printf("k=%v v=%v \n",k,v)
}
//使用 for-range遍历一个结构比较复杂的map
stuMap:=make(map[string]map[string]string)
stuMap["stu01"]=make(map[string]string,3)
stuMap["stu01"]["name"]="tom"
stuMap["stu01"]["sex"]="男"
stuMap["stu01"]["address"]="北京"
stuMap["stu02"]=make(map[string]string,3)
stuMap["stu02"]["name"]="alex"
stuMap["stu02"]["sex"]="男"
stuMap["stu02"]["address"]="广西"
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的长度
func len
func len(v Type)int
内建函数len返回v的长度,这取决于具体类型:
数组: v中元素的数量
数组指针:*v 中元素的数量(v为nil时panic)
切片,映射:v中元素的数量,看v为nil,len(v)即为零
字符串:v中字节的数量
通道:通道缓存中队列(未读取)元素的数量,若v 为 nil,len(v)即为零
fmt.Println(len(stuMap))
6.map切片
1.基本介绍
切片的数据类型如果是map,则我们称为slice of map,map切片,这样使用则
map这个数就可以动态变化了
2.案例演示
要求:使用一个map来记录美女的信息,name和age,
也就是说一个美女对应一个map,并且美女的个数可以动态增加
package main
import "fmt"
func main() {
var mm []map[string]string
mm=make([]map[string]string,2)//准备放入两个美女
//增加第一个mm的信息
if mm[0]==nil{
mm[0]=make(map[string]string,2)
mm[0]["name"]="韩雪"
mm[0]["age"]="28"
}
if mm[1]==nil{
mm[1]=make(map[string]string,2)
mm[1]["name"]="章子怡"
mm[1]["age"]="38"
}
//这种写法会导致越界
//if mm[2]==nil{
// mm[2]=make(map[string]string,2)
// mm[2]["name"]="章子怡"
// mm[2]["age"]="38"
//}
//这里我们需要使用到切片的append函数,可以动态增加mm
//先定义个mm的信息
mm2:=map[string]string{
"name":"柳如是",
"age":"468",
}
mm=append(mm,mm2)
fmt.Println(mm)
}
7.map排序
1.基本介绍
1》golang中没有一个专门的方法针对map的key进行排序
2》golang中得map默认是无序的,注意也不是按照添加的顺序存放的,你每次遍历,得到的输出可能不一样
3》golang中的Map的排序,是先将Key进行排序,然后根据Key值遍历输出即可
2,案例演示
package main
import (
"fmt"
"sort"
)
func main() {
//map的排序
map1:=make(map[int]int,10)
map1[10]=100
map1[1]=8
map1[6]=7
map1[3]=5
fmt.Println(map1)
//如果按照map的key的排序进行输出
//1.现将Map的key放入到切片中
//2.对切片排序
//3.遍历切片,然后按照key来输出Map的值
var keys[]int
for k,_:=range map1{
keys=append(keys,k)
}
//排序
sort.Ints(keys)
fmt.Println(keys)
//
for _,k:=range keys{
fmt.Printf("map1[%v]=%v \n",k,map1[k])
}
}
8.map的使用细节
1》map是引用类型,遵守引用类型传递的机制,在一个函数接收map,修改后,会直接修改原来的map
package main
import "fmt"
func modify(map1 map[int]int) {
map1[10]=1000
}
func main() {
map1:=make(map[int]int)
map1[1]=10
map1[2]=20
map1[10]=999
modify(map1)
//map1[10]=1000,说明Map遵循引用类型的传递机制
fmt.Println(map1)
}
2)map的容量到达后,再想map增加元素,会自动扩容,并不会发生panic,也就是说 map的容量是动态增长的
3)map的value也经常使用struct类型,更适合管理复杂的数据(比前面value是一个map更好),比如:value为 Studetnt结构体
结构体:初体验
9.map的练习
1》使用map[string]map[string]string 的map类型
2》key:表示用户名,是唯一的,不可以重复
3》如果某个用户名存在,就将其密码修改“666666”,如果不存在就增加这个用户信息,包括昵称(name,密码pwd)
4》编写一个函数modifyUser(users map[string]map[string]string,name string)
package main
import "fmt"
func modifyUsers(users map[string]map[string]string,name string){
//判断users中是否有name
if users[name]!=nil{
//有这个用户
users[name]["pwd"]="8888"
}else {
//没有这个用户
users[name]= make(map[string]string,2)
users[name]["pwd"]="8888"
users[name]["name"]="昵称"+name
}
}
func main() {
users:=make(map[string]map[string]string,10)
users["zhangsan"]=make(map[string]string,3)
users["zhangsan"]["pwd"]="12345"
users["zhangsan"]["name"]="擎天柱"
modifyUsers(users,"tome")
modifyUsers(users,"zhangsan")
modifyUsers(users,"lily")
fmt.Println(users)
}