您的位置:首页 > 编程语言

Go基础编程——map

2018-01-17 15:51 274 查看
map

1、类 似 其 它 浯 言 中 的 唁 希 表 或 者 字 典 , 以 key-value形式存储数据 :

2、Key必须 是 支 持==或 ! = 比 较 运 算 的 类 型 , 不 可 以 是函数、 map或者slice

3、Map查找 比 线 性 搜 索 快 很 多 , 但 比 使 用 索 引(数组,Slice等) 访 问 数 据 的 类 型 慢 100 倍

4、Map使用make()创建 , 支 持:=这 种 简 写 方 式

5、make([keyType]valueType, cap) , cap 表 示 容 量 , 可 省 略

6、超 出 容 量 时 会 自 动 扩 容 , 但 尽 量 提供 一 个 台 理 的 初 始 值

7、使用len()获 取 元 素 个数

8、键值 对 不 存 在 时 自 动 添 加 , 使 用delete() 删 除 某键值对

9、使 用 for range 对 map 和Slice 进 行 迭 代 操 作

创建一个空的map

m:=map[int]string{}
fmt.Println(m)


其中int是key的类型,string是value的类型。

使用make()来创建map的方式如下:

n:=make(map[int]string)

m[1]="Hello"


可以使用这样的方式给map赋值。

a:=m[1]


使用这样的方式取出值。同时删除一个值可以使用如下程序来完成:

m:=map[int]string{}
m[1]="Hello"
a:=m[1]
fmt.Println(m)
delete(m,1)
fmt.Println(m)
/*n:=make(map[int]string)
fmt.Println(n)*/
fmt.Println(a)


运行结果

map[1:Hello]
map[]
Hello


这样就实现了删除一个元素。delete(m,1)第一个参数m是指的要删除的元素所在的map类型,1代表要删除的元素的key值。

当然企业级开发都是使用复杂的map来实现功能的,接下来就试试:

m:=make(map[int]map[int]string)
m[1]=make(map[int]string)
fmt.Println(m)
m[1][1]="Hello"
a:=m[1][1]
fmt.Println(m)
fmt.Println(a)


运行结果

map[1:map[]]
map[1:map[1:Hello]]
Hello


可以看到第一次初始化只是对最外层进行了初始化,第二次才是到里层。这里有两种方法检查map是否被初始化。

第一种方法就是直接取那个值,如下

m:=make(map[int]map[int]string)
m[1]=make(map[int]string)
fmt.Println(m)
//m[1][1]="Hello"
a:=m[1][1]
fmt.Println(m)
fmt.Println(a)


这时候fmt.Println(a)得到就是一个空字符串,

这里推荐第二种方法,使用多返回值的特性返回一个bool类型更加好判断是否有值,以便在合适的时候给它初始化。示例程序如下:

m:=make(map[int]map[int]string)
m[1]=make(map[int]string)
fmt.Println(m)
//m[1][1]="Hello"
a,ok:=m[1][1]
if !ok{
m[1][1]="Hello"
}
a=m[1][1]
fmt.Println(m)
fmt.Println(a)


运行结果

map[1:map[]]
map[1:map[1:Hello]]
Hello


这样就实现了,首先判断出某个值未被赋值的时候给他在合适的地方初始化。记住一个核心点,多个map嵌套的时候每一级都要进行单独的初始化。

Slice与map结合的使用场景

sm:=make([]map[int]string,3)
for _,v:=range sm{
v=make(map[int]string,1)
v[1]="China"
fmt.Println(v)
}
fmt.Println(sm)


运行结果

map[1:China]
map[1:China]
map[1:China]
[map[] map[] map[]


这个就是以map为类型,初始值为3个的Slice

这种形式初始化的sm是空值,因为循环遍历出来的v只是一个拷贝,在计算机中的地址不是原来的内存地址,所以,给拷贝出来的v赋值不会影响到sm中对应的v值。下边来看看每次的循环拷贝出来的内存地址和原来sm的内存地址不一样,就可以解释了,看如下程序:

sm:=make([]map[int]string,3)
for _,v:=range sm{
v=make(map[int]string,1)
v[1]="China"
fmt.Println(v)
fmt.Printf("%p\n",v)
}
fmt.Println(sm)
fmt.Printf("%p\n",sm)


运行结果

map[1:China]
0xc042068060
map[1:China]
0xc042068090
map[1:China]
0xc0420680c0
[map[] map[] map[]]
0xc0420023e0


可以看出每次拷贝都是放在不同内存地址。一般情况我们希望通过循环来给sm初始化赋值,这时候只需要获取返回来的索引就可以解决问题,看如下解决办法:

sm:=make([]map[int]string,3)
for i,_:=range sm{
sm[i]=make(map[int]string,1)
sm[i][1]="China"
fmt.Println(sm[i])
fmt.Printf("%p\n",sm[i])
}
fmt.Println(sm)
fmt.Printf("%p\n",sm)


运行结果

map[1:China]
0xc04207a060
map[1:China]
0xc04207a090
map[1:China]
0xc04207a0c0
[map[1:China] map[1:China] map[1:China]]
0xc0420443a0


这样以索引的形式赋值,就不会是空的,索引是在内存中是唯一的,这样就就能够对迭代对象进行直接拷贝。

map是无序性的,但是很多时候需要map间接的成为有序的,这时候就需要借助Slice,主要是通过给map的key值进行排序来达到对map的排序,看如下程序:

m:=map[int]string{1:"a",2:"b",3:"c",4:"d",5:"e"}
s:=make([]int,len(m))
i:=0
for k,_:=range m  {
s[i]=k
i++
}
sort.Ints(s)
fmt.Println(s)
for i=1;i<=len(s);i++{
for k,_:=range m{
if k==i{
a:=m[k]
fmt.Print(a)
}
}
}


运行结果

[1 2 3 4 5]
abcde


思考

使用for range尝试将类型为map[int]string的键和值进行交换,是它变成map[string]int

如下所示;

m1:=map[int]string{1:"a",2:"b",3:"c"}
m2:=make(map[string]int)
for k,v:=range m1{
m2[v]=k
}
fmt.Print(m1,m2)


运行结果

map[1:a 2:b 3:c] map[a:1 b:2 c:3]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: