map—建立事务关联的容器
应用场景:需要使用任意类型的关联关系时,需要用到映射。如学号和学生,名字与档案。
底层实现:使用散列表实现。
散列表实现,所以查找时间复杂度为O(1),最坏情况为O(n),n为元素总数。
注意:
- key必须是支持==或者!=比较运算的类型,不可以是函数,map或slice类型
- Map查找比线性搜索快很多,但比使用索引访问数据的类型慢100倍
- Map使用make()创建,支持:=这种简写方式。
1.添加关联map并访问关联和数据。
定义:
map[keyType]ValueType
示例:
m := map[string]string{
"W":"forward",
"A":"left"
}
用make创建:
scene :=make(map[string]int)
复杂类型的map创建:
var m map[int]map[int]string
m= make(map[int]map[int][string])
m[1]=make(map[int][string])
m[1][1]="ok"
a:= m[1][1]
fmt.Println(a)
输出:ok
某些情况下,需要明确知道查询中某个键是否在map中存在,可以使用这种写法:
v,ok :=scene["route"]
如果ok为nil,表示value不存在。
2.遍历map的"键值对"
func main() {
scene := map[string]int{
"route": 64,
"brazil": 4,
"china": 960,
}
for k, v := range scene {
fmt.Println(k, v)
}
}
如果需要特定的顺序的遍历结果,正确的做法是排序。
对map中的值进行排序,示例如下:
func main() {
scene := map[string]int{
"route": 64,
"brazil": 4,
"china": 960,
}
//声明一个切片保存map的键值数据
var sceneList []string
for k :=range scene{
sceneList =append(sceneList,k)
}
//对切片进行排序
sort.Strings(sceneList)
}
3.使用delete()函数从map中删除键值对
格式:
delete(map,键值)
func main() {
scene := map[string]int{
"route": 64,
"brazil": 4,
"china": 960,
}
//删除brazil的键值对
delete (scene,"brazil")
4.清空map中的所有元素
因为垃圾回收的原因,不需要清空,重新make即可
5.在并发环境中使用map
Go语言中的map在并发的情况下,只读是线程安全的,同时读写线程不安全。需要并发进行读写时,一般的做法是加锁,但是这样的性能并不高,Go语言1.9版本中提到了一种效率较高的并发安全的sync.Map.
它有以下的特性:
- 无须初始化,不能使用map的方式进行
- 和map取值和设置等操作不同,它是使用方法进行调用。Store表示存储,Load表示获取,Delete表示删除。
- 使用range 配合一个回调函数进行遍历操作。
syc.map示例代码:
func main() {
var scene sync.Map
//将键值对保存到sync.Map
scene.Store("greece", 97)
scene.Store("london", 100)
scene.Store("egypt", 200)
//从sync.Map中根据键取值
fmt.Println(scene.Load("london"))
//删除
scene.Delete("london")
//遍历
scene.Range(func(k, v interface{}) bool {
fmt.Println("iterate:", k, v)
return true
})
}
sync.Map没有提供map数量的方法,替代方法是获取时遍历自行计算数量。因为为了保证并发安全有一些性能损失,因此非并发的情况下,使用map相比使用sync.Map有更好 的性能。