首页 > 其他分享 >Go 语言 map 如何顺序读取?

Go 语言 map 如何顺序读取?

时间:2023-05-27 09:55:05浏览次数:37  
标签:map 遍历 读取 bucket 顺序 key Go

原文链接: 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。这样就可以按照特定顺序输出键值对了。

以上就是本文的全部内容,如果觉得还不错的话欢迎点赞转发关注,感谢支持。


参考文章:

推荐阅读:

标签:map,遍历,读取,bucket,顺序,key,Go
From: https://www.cnblogs.com/alwaysbeta/p/17436312.html

相关文章

  • Go 语言 map 是并发安全的吗?
    原文链接:Go语言map是并发安全的吗?Go语言中的map是一个非常常用的数据结构,它允许我们快速地存储和检索键值对。然而,在并发场景下使用map时,还是有一些问题需要注意的。本文将探讨Go语言中的map是否是并发安全的,并提供三种方案来解决并发问题。先来回答一下题目的问......
  • 【模型部署 01】C++实现分类模型(以GoogLeNet为例)在OpenCV DNN、ONNXRuntime、TensorRT
    深度学习领域常用的基于CPU/GPU的推理方式有OpenCVDNN、ONNXRuntime、TensorRT以及OpenVINO。这几种方式的推理过程可以统一用下图来概述。整体可分为模型初始化部分和推理部分,后者包括步骤2-5。以GoogLeNet模型为例,测得几种推理方式在推理部分的耗时如下:结论:GPU加速首选Tens......
  • 云服务器运行django项目
    打开项目的settings.py文件。在文件中找到ALLOWED_HOSTS设置。它应该是一个包含字符串的列表。将服务器的IP地址(在此示例中是XX.XX.xx.xx)添加到ALLOWED_HOSTS列表中。确保不要删除已存在的任何其他允许的主机。ALLOWED_HOSTS=['ip','your-domain.com']或者......
  • 前端热力图组件heatMapGD中国地图 中国热力地图 广东省热力地图 广东省地图 地市选择
    快速实现前端中国热力地图广东省热力地图广东省地图,请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin?id=12407 #china广东省热力地图使用方法#map数据获取链接:http://datav.aliyun.com/portal/school/atlas/area_selector 效果图如下:  ####HTML......
  • 2023-05-26:golang关于垃圾回收和析构函数的选择题,多数人会选错。
    2023-05-26:golang关于垃圾回收和析构的选择题,代码如下:packagemainimport( "fmt" "runtime" "time")typeListNodestruct{ Valint Next*ListNode}funcmain0(){ a:=&ListNode{Val:1} b:=&ListNode{Val:2} runtime.SetFi......
  • Django - makemigrations - No changes detected
    Django-makemigrations-Nochangesdetected回答1Tocreateinitialmigrationsforanapp,runmakemigrationsandspecifytheappname.Themigrationsfolderwillbecreated../manage.pymakemigrations<myapp>YourappmustbeincludedinINSTALLED......
  • golang的iota使用
    1、iota是什么iota是常量的计数器,可理解为const定义常量的行数的索引,注意是行数。const中每新增一行常量声明将使iota计数一次,前提是iota在const中出现。2、应用场景一般用于枚举数据3、易错点因为iota一般出现在const语句块的第一行,不少初学者会将之认为io......
  • discoDSP Vertigo for Mac(声音合成插件) v4.4S中文版
    通过加法合成发现声音设计的无限可能性,加法合成是一种通过将两个或多个音频信号相加而产生新声音的合成。VertigoAdditiveSynthesizer提供了一系列功能来增强您的创作潜力,包括256个振荡器,双滤波器和8种易于操作和修改的效果。discoDSPVertigo中文版插件功能特色我们的合成器......
  • GO基准测试
    如何确定N的循环次数不变量:时间,一般为1s,可以外部运行时指定关键代码func(b*B)launch(){ //Signalthatwe'redonewhetherwereturnnormally //orbyFailNow'sruntime.Goexit. deferfunc(){ b.signal<-true }() //Runthebenchmarkforatleastthe......
  • Django——AJAX
    AJAX(AsynchronousJavascriptAndXML)翻译成中文就是“异步的Javascript和XML”。AJAX不是新的编程语言,而是一种使用现有标准的新方法。使用Javascript语言与服务器进行异步交互的,并进行局部刷新。传输的数据为XML(当然,传输的数据不只是XML)AJAX最大的优点是在不重新加载整个......