golang语言map的并发和排序
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang语言map的并发和排序相关的知识,希望对你有一定的参考价值。
参考技术A golang语言map的并发和排序golang缺省的map不是thread safe的,如果存在读写并发的使用场景,必须在外面使用lock机制。
包sync里面引入一个安全map;
用法:
运行结果如下:
golang官方说法map并不排序,不按key排序,也不按插入顺序排序,也就是说map是无序的,无法保证任何排序。
下面是一种常见的给map排序输出的办法:
Golang:map的定义操作排序以及map切片
map概述
golang中的引用类型。
与其他语言中的map类型基本相似,都是k-v形式的,k不可重复,元素是无序的,并且支持扩容。
基本语法
var 变量名 map[keytype]valuetype
key可以是很多类型
bool、数字、string、指针、channel,还可以是只包含前面几种类型的 接口、结构体、数组。
但是!!!slice、map、function是不可以作为map的key,因为无法使用 == 判断key是否相等。
value的类型就没有特别的要求
声明
map的声明是不会分配内存的,初始化需要make,分配内存后才能赋值和使用。
map的声明示例
package main
import "fmt"
//声明一个map变量
var map1 map[string]string
func main()
//第一种方式:先声明,再make
fmt.Printf("map1=%v\\n", map1)
fmt.Printf("map1 address=%p\\n", &map1) //变量map1是有内存地址的
fmt.Printf("map1==nil? %v\\n", map1 == nil) //在没有make之前map1==nil为true成立,代表没有分配内存空间
//使用map要先make
map1 = make(map[string]string, 2) //分配了2个空间
map1["LeoLee"] = "18"
fmt.Printf("map1=%v, length=%d\\n", map1, len(map1))
map1["Lydia"] = "18"
fmt.Printf("map1=%v, length=%d\\n", map1, len(map1))
map1["LeoLee"] = "26"
fmt.Printf("map1=%v, length=%d\\n", map1, len(map1))
map1["Tony"] = "1" //map会自动扩容
fmt.Printf("map1=%v, length=%d\\n", map1, len(map1))
//第二种方式:声明map变量的同时,make
map2 := make(map[string]int) //这里不定义初始size,根据内置函数make的api说明,会分配一个默认起始大小:0
fmt.Printf("map2=%v, length=%d\\n", map2, len(map2))
map2["a"] = 1
map2["b"] = 2
fmt.Printf("map2=%v, length=%d\\n", map2, len(map2))
//第三种方式:声明直接赋值
map3 := map[int]string
1: "c",
2: "d",
fmt.Printf("map3=%v, length=%d\\n", map3, len(map3))
操作map
map的增删改查、以及循环遍历(map只能使用for range遍历):
package main
import "fmt"
func main()
//map删除元素,使用内置函数delete
map1 := map[string]string
"a": "欸",
"b": "币",
"c": "西",
delete(map1, "a") // 若map为nil或无此元素,delete不进行操作
delete(map1, "d")
fmt.Printf("map1=%v, length=%d\\n", map1, len(map1))
//golang的map没有办法一次性删除所有的key-value,需要遍历删除
for k, _ := range map1
delete(map1, k)
fmt.Printf("map1=%v, length=%d\\n", map1, len(map1))
//或者对该map变量重新进行make初始化(指向新的内存地址),让该map变量对应的原来的引用对象成为垃圾。
map1 = make(map[string]string)
fmt.Printf("map1=%v, length=%d\\n", map1, len(map1))
//获取对应key的value
map2 := map[string]string
"a": "欸",
"b": "币",
"c": "西",
val1, getRes1 := map2["a"]
fmt.Printf("key:a, value:%s, getRes1:%v\\n", val1, getRes1)
val2, getRes2 := map2["d"]
fmt.Printf("key:d, value:%s, getRes2:%v\\n", val2, getRes2)
//遍历,map的遍历只能使用for range方式
for k, v := range map2
fmt.Println(k, v)
map切片
map切片类似于Java中的List<Map>或者是Array<Map>
package main
import "fmt"
//map切片,类似于Java中List<Map>
func main()
personSlice := make([]map[string]string, 2, 2)
personSlice[0] = make(map[string]string)
personSlice[0]["name"] = "LeoLee"
personSlice[0]["age"] = "26"
personSlice[1] = make(map[string]string)
personSlice[1]["name"] = "Lydia"
personSlice[1]["age"] = "29"
//如果继续追加,会有越界
/*personSlice[2] = make(map[string]string)
personSlice[2]["name"] = "Lydia"
personSlice[2]["age"] = "29"*/
//所以需要使用slice的append,这样切片可以动态扩容
personMap1 := make(map[string]string)
personMap1["name"] = "Tony"
personMap1["age"] = "30"
personSlice = append(personSlice, personMap1)
for _, m := range personSlice
fmt.Println(m)
map的排序
由于Golang中没有提供原生的有序map,所以Golang中的有序map需要开发者自己实现,以下是一个对map进行有序输出的小例子:
package main
import (
"fmt"
"sort"
)
//map排序
func main()
//在老版本中,使用print输出map也会是无序的,新版本中变为升序
//但是遍历map仍然是无序的
map1 := map[int]string
3: "b",
2: "a",
6: "c",
5: "e",
fmt.Println("map1=", map1)
for k, v := range map1
fmt.Printf("%d:%s\\n", k, v)
map2 := make(map[string]string)
map2["b"] = "1"
map2["a"] = "4"
map2["g"] = "2"
map2["f"] = "8"
fmt.Println("map2=", map2)
for k, v := range map2
fmt.Printf("%s:%s\\n", k, v)
//对map进行排序
/*1.先将map的key放入切片中
2.对切片进行排序
3.遍历切片,按照切片遍历的顺序获取key对应的value*/
var keys1 []int
for k, _ := range map1
keys1 = append(keys1, k)
fmt.Printf("keys1=%v\\n", keys1)
//使用sort包下的Ints函数,Ints函数将会把传入的int类型切片按照递增顺序排序
sort.Ints(keys1)
fmt.Printf("keys1=%v\\n", keys1)
for _, key := range keys1
val, _ := map1[key]
fmt.Println(key, ":", val)
以上是关于golang语言map的并发和排序的主要内容,如果未能解决你的问题,请参考以下文章