Go 语言 map 如何顺序读取?
Posted AlwaysBeta
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go 语言 map 如何顺序读取?相关的知识,希望对你有一定的参考价值。
原文链接: Go 语言 map 如何顺序读取?
Go 语言中的 map 是一种非常强大的数据结构,它允许我们快速地存储和检索键值对。
然而,当我们遍历 map 时,会有一个有趣的现象,那就是输出的键值对顺序是不确定的。
现象
先看一段代码示例:
package main
import "fmt"
func main()
m := map[string]int
"apple": 1,
"banana": 2,
"orange": 3,
for k, v := range m
fmt.Printf("key=%s, value=%d\\n", k, v)
当我们多执行几次这段代码时,就会发现,输出的顺序是不同的。
原因
首先,Go 语言 map 的底层实现是哈希表,在进行插入时,会对 key 进行 hash 运算。这也就导致了数据不是按顺序存储的,和遍历的顺序也就会不一致。
第二,map 在扩容后,会发生 key 的搬迁,原来落在同一个 bucket 中的 key,搬迁后,有些 key 可能就到其他 bucket 了。
而遍历的过程,就是按顺序遍历 bucket,同时按顺序遍历 bucket 中的 key。
搬迁后,key 的位置发生了重大的变化,有些 key 被搬走了,有些 key 则原地不动。这样,遍历 map 的结果就不可能按原来的顺序了。
最后,也是最有意思的一点。
那如果说我已经初始化好了一个 map,并且不对这个 map 做任何操作,也就是不会发生扩容,那遍历顺序是固定的吗?
答:也不是。
Go 杜绝了这种做法,主要是担心程序员会在开发过程中依赖稳定的遍历顺序,因为这是不对的。
所以在遍历 map 时,并不是固定地从 0 号 bucket 开始遍历,每次都是从一个随机值序号的 bucket 开始遍历,并且是从这个 bucket 的一个随机序号的 cell 开始遍历。
如何顺序读取
如果希望按照特定顺序遍历 map,可以先将键或值存储到切片中,然后对切片进行排序,最后再遍历切片。
改造一下上面的代码,让它按顺序输出:
package main
import (
"fmt"
"sort"
)
func main()
m := map[string]int
"apple": 1,
"banana": 2,
"orange": 3,
// 将 map 中的键存储到切片中
keys := make([]string, 0, len(m))
for k := range m
keys = append(keys, k)
// 对切片进行排序
sort.Strings(keys)
// 按照排序后的顺序遍历 map
for _, k := range keys
fmt.Printf("key=%s, value=%d\\n", k, m[k])
在上面的代码中,首先将 map 中的键存储到一个切片中,然后对切片进行排序。
最后,按照排序后的顺序遍历 map。这样就可以按照特定顺序输出键值对了。
以上就是本文的全部内容,如果觉得还不错的话欢迎点赞,转发和关注,感谢支持。
参考文章:
推荐阅读:
吴裕雄--天生自然--Go 语言学习笔记--Go 语言Map(集合)
Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。
Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。
定义 Map 可以使用内建函数 make 也可以使用 map 关键字来定义 Map: /* 声明变量,默认 map 是 nil */ var map_variable map[key_data_type]value_data_type /* 使用 make 函数 */ map_variable := make(map[key_data_type]value_data_type) 如果不初始化 map,那么就会创建一个 nil map。nil map 不能用来存放键值对 实例 下面实例演示了创建和使用map: 实例 package main import "fmt" func main() { var countryCapitalMap map[string]string /*创建集合 */ countryCapitalMap = make(map[string]string) /* map插入key - value对,各个国家对应的首都 */ countryCapitalMap [ "France" ] = "巴黎" countryCapitalMap [ "Italy" ] = "罗马" countryCapitalMap [ "Japan" ] = "东京" countryCapitalMap [ "India " ] = "新德里" /*使用键输出地图值 */ for country := range countryCapitalMap { fmt.Println(country, "首都是", countryCapitalMap [country]) } /*查看元素在集合中是否存在 */ capital, ok := countryCapitalMap [ "American" ] /*如果确定是真实的,则存在,否则不存在 */ /*fmt.Println(capital) */ /*fmt.Println(ok) */ if (ok) { fmt.Println("American 的首都是", capital) } else { fmt.Println("American 的首都不存在") } } 以上实例运行结果为: France 首都是 巴黎 Italy 首都是 罗马 Japan 首都是 东京 India 首都是 新德里 American 的首都不存在
delete() 函数 delete() 函数用于删除集合的元素, 参数为 map 和其对应的 key。实例如下: 实例 package main import "fmt" func main() { /* 创建map */ countryCapitalMap := map[string]string{"France": "Paris", "Italy": "Rome", "Japan": "Tokyo", "India": "New delhi"} fmt.Println("原始地图") /* 打印地图 */ for country := range countryCapitalMap { fmt.Println(country, "首都是", countryCapitalMap [ country ]) } /*删除元素*/ delete(countryCapitalMap, "France") fmt.Println("法国条目被删除") fmt.Println("删除元素后地图") /*打印地图*/ for country := range countryCapitalMap { fmt.Println(country, "首都是", countryCapitalMap [ country ]) } } 以上实例运行结果为: 原始地图 India 首都是 New delhi France 首都是 Paris Italy 首都是 Rome Japan 首都是 Tokyo 法国条目被删除 删除元素后地图 Italy 首都是 Rome Japan 首都是 Tokyo India 首都是 New delhi
以上是关于Go 语言 map 如何顺序读取?的主要内容,如果未能解决你的问题,请参考以下文章