Go基础编程——map

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]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章