当前位置: 首页 > news >正文

Golang Map原理(底层结构、查找/新增/删除、扩缩容)

参考:

  • 解剖Go语言map底层实现
  • Go语言核心手册-3.字典

一、Go Map底层结构:

Go map的底层实现是一个哈希表数组 + 链表),使用拉链法消除哈希冲突,因此实现map的过程实际上就是实现哈希表的过程。

先来看下go map底层的具体结构:

type hmap struct {count      int            // 元素个数,调用len(map)返回这个值B          uint8          // bucket数量是2^B, 最多可以放 loadFactor * 2^B 个元素,再多就要扩容了hash0      uint32         // hash seedbuckets    unsafe.Pointer // 指向bucket数组的指针(存储key val);大小:2^B oldbuckets unsafe.Pointer // 扩容时,buckets 长度是 oldbuckets 的两倍// ...
}
type bmap struct {topbits  [8]uint8     // 高位哈希值数组keys     [8]keytype   // 存储key的数组values   [8]valuetype // 存储val的数组overflow uintptr      // 指向当前bucket的溢出桶// 为缓解当存在多个key计算后的哈希值低8位相同的个数大于一个bucket所能存放的数目8个时,且这个map还没达到扩容条件时,做的一种存储设计。
}

在这里插入图片描述
在这个哈希表中,主要涉及到的结构体有两个:一个是 hmap(a header for a go map),一个是 bmap(a bucket for a go map):

  • 对于 hmap,我们只需要关注其中的 buckets,它是一个指向 bmap结构体类型数组的指针。
    • 而对于其中的 bmap
      • 高位哈希值 topbits:数组记录的是当前bucket中key相关的 “索引”
      • 指向扩容bucket的指针 overflow:每个 bmap类型的 bucket 最多只能放 8个k-v键值对。如果碰巧有key的哈希值一样的新数据存入当前bucket,那就需要再构建一个新的溢出桶 bucket,并通过overflow指针连接起来,使得bucket形成一个链表结构。
      • 存储key/value的数组 keysvalues

二、key-value是如何存放的:

当前bucket桶中的 key-value 的值的存放是有其特点的,bucket桶中所有的key存放到 keys数组中,而所有的value存放到 values数组中。
这么做的原因也很简单,可以在key和value的长度不同时,消除padding(内存对齐)带来的空间浪费。具体如图所示:
在这里插入图片描述

三、根据key 查找/新增 数据:

对传来的key进行哈希运算得到唯一哈希值,并将该哈希值分为高位和低位,如图所示:
在这里插入图片描述
蓝色为高位,红色为低位。 低位用于寻找当前key属于哪个bucket,而高位用于寻找对应bucket中的具体key

而之前 bmap中的高位哈希值数组字段 topbits,存的就是当前bucket桶中不同key-value键值对中对应key的高位哈希值,这样便于根据key查找数据。

新增的过程与查找过程类似,也是填充桶的过程。

四、删除map中的数据

针对map中的key-value数据:

  • 如果是指针类型数据,则将其原有引用去除,利用go GC来清理内存
  • 如果是类型数据,则直接清理对应内存空间

最后将该key-value记录对应的 【bmap中高位哈希值数组 topbits】中的key相关 “索引” 置空。

五、map的扩容

当go map中每个bucket桶存储的平均元素个数大于加载因子 loadFactor = 6.5(判断扩容的条件)时,map底层就会创建一个容量大小是原来2倍的新buckets数组,并将 oldbuckets指针指向原来的旧buckets数组。然后,对旧buckets数组中的元素key重新哈希(rehash)得到新的哈希值,根据新的哈希值的高位和低位来放入扩容后的新buckets数组中。

加载因子越小↓,说明空间利用率低,因此 “产生冲突的机会” 低;
加载因子越大↑,说明空间利用率高,但是 “产生冲突的机会” 也高了。

不过需要注意的是:

并不是立刻把 oldbuckets指针所指向的旧bucket数组中的元素一次性转移到新的bucket数组当中,而是当只有访问到具体某个key所在的bucket时,才会将该bucket中的旧数据逐步迁移到新bucket中。一直到旧数据完全迁移完,才会删除 oldbuckets的指向,使得旧buckets空间得到释放。如下图所示:
在这里插入图片描述
这里迁移完并不会直接删除旧bucket中的数据,而是把原来旧数据的引用去掉,利用GC逐步清除内存

六、map的等量扩容(缩容)

map中数据较少,但 overflow 指向的溢出桶bucket数量过多时,会导致溢出桶中的记录存储很稀疏,排列不紧凑,大量空间被浪费。这时就需要进行等量扩容/缩容(一般出现在之前数据被大量删除的场景下)。

其实就是重新整理一下数据,使溢出桶中的数据重新紧凑的放在普通bucket桶中,避免不必要的空间浪费。

相关文章:

Golang Map原理(底层结构、查找/新增/删除、扩缩容)

参考: 解剖Go语言map底层实现Go语言核心手册-3.字典 一、Go Map底层结构: Go map的底层实现是一个哈希表(数组 链表),使用拉链法消除哈希冲突,因此实现map的过程实际上就是实现哈希表的过程。 先来看下…...

Java_数组

数组 1.概念 ​ 需求:现在需要统计软件技术1班47名同学的成绩情况,例如计算平均成绩、最高成绩等。如果只能使用变量的话,那么需要定义100个变量,这样就比较复杂了。这时我们就可以使用数组来记住这47名同学的成绩,然…...

list与vector的区别

相信大家已经学过list与vector,关于它们的不同,我做了一些总结,如下表: vector list底层结构动态顺序表,一段连续的空间带头结点的双向链表随机访问支持随机访问,访问某个元素的效率…...

【C++、数据结构】位图、布隆过滤器、哈希切割(哈希思想的应用)

文章目录📖 前言1. 位图1.1 海量数据处理思路分析:1.2 位图的具体实现:1.3 用位图解决问题:应用一:应用二:应用三:2. 布隆过滤器2.1 布隆过滤器的概念:2.2 布隆过滤器的测试&#xf…...

计算机网络安全基础知识3:网站漏洞,安装phpstudy,安装靶场漏洞DVWA,搭建一个网站

计算机网络安全基础知识3:网站漏洞,安装phpstudy,安装靶场漏洞DVWA,搭建一个网站 2022找工作是学历、能力和运气的超强结合体,遇到寒冬,大厂不招人,可能很多算法学生都得去找开发,测…...

大话数据结构-迪杰斯特拉算法(Dijkstra)和弗洛伊德算法(Floyd)

6 最短路径 最短路径,对于图来说,是两顶点之间经过的边数最少的路径;对于网来说,是指两顶点之间经过的边上权值之和最小的路径。路径上第一个顶点为源点,最后一个顶点是终点。 6.1 迪杰斯特拉(Dijkstra&am…...

2023年全国最新食品安全管理员精选真题及答案10

百分百题库提供食品安全管理员考试试题、食品安全员考试预测题、食品安全管理员考试真题、食品安全员证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。 91.实施日常检查,如果违反关键项的,应当即作出如…...

Unity常见面试题详解(持续更新...)

一丶声明、定义、实例化、初始化 1、首先我们来讨论在C/C中的声明和定义.. 1)我们先从函数声明和定义说起... 一般我们在C里都会先定义一个函数,然后再Main函数前将函数声明,比如: //函数声明 int Add(int);int Main {} //函数…...

java高级篇之三大性质总结:原子性、可见性以及有序性

1. 三大性质简介 在并发编程中分析线程安全的问题时往往需要切入点,那就是两大核心:JMM抽象内存模型以及happens-before规则(在这篇文章中已经经过了),三条性质:原子性,有序性和可见性。关于sy…...

真涨脸,我用 Python 为朋友自动化整理表格

今天,在工作的时候,我的美女同事问我有没有办法自动生成一个这样的表格: 第一列是院校科目,第二列是年份,第三列是数量。 这张表格是基于这一文件夹填充的,之前要一个文件夹一个文件夹打开然后手动填写年份…...

MySQL学习笔记(1.操作数据库与数据的SQL)

1. 下载安装 参照:MySQL8.0下载安装_凯尔萨厮的博客-CSDN博客 2. MySQL启动与停止 方式(1).我的电脑>右键>管理>服务和应用程序>服务>(或在windows搜索栏输入services.msc) 找到MySQL80,右键启动或停止 方式(2…...

C++——特殊类设计

目录 不能被拷贝的类 只能在堆上创建对象的类 只能在栈上创建对象的类 不能被继承的类 只能创建一个对象的类(单例模式) 饿汉模式 懒汉模式 单例对象释放问题 不能被拷贝的类 C98:将拷贝构造函数与赋值运算符重载只声明不定义,并且将其访问权…...

Scratch少儿编程案例-植物大战僵尸-趣味角色版

专栏分享 点击跳转=>Unity3D特效百例点击跳转=>案例项目实战源码点击跳转=>游戏脚本-辅助自动化点击跳转=>Android控件全解手册点击跳转=>Scratch编程案例👉关于作者...

Vue的路由守卫

对于绝大部分的网站而言,都是有个人主页的,但是你如果没登陆的话,还能访问个人主页吗? 从逻辑上来讲,那肯定是不行的。 所以,要怎么阻止没登录状态下去访问个人主页呢? 就是利用路由守卫&#x…...

【算法】151. 反转字符串中的单词

链接:https://leetcode.cn/problems/reverse-words-in-a-string/给你一个字符串 s ,请你反转字符串中 单词 的顺序。单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。返回 单词 顺序颠倒且 单词 之间用单个空格连接的结…...

Azure AI基础到实战(C#2022)-认知服务(2)

目录 ComputerVisionClient Class定义构造函数属性上一节例子Task.Wait 方法其它部分分析winform调用认知服务代码剖析1、调用参数2、定义ComputerVisionClient对象,准备调用 REST API3、Authenticate4、调用REST API,这是重点和关键(1)Lambda 表达式和匿名函数(2)async(3)…...

并发就一定快吗?答:肯定不是啊

文章目录一、多线程概念1.1 程序的并发与并行1.1.1 程序的并行1.1.2 程序的并发1.2 进程与线程1.2.1 进程1.2.2 线程1.2.3 多线程并发就一定快吗?答案直接戳这里👉:多线程并发就一定快吗? 一、多线程概念 在实际应用中&#xff…...

前端的学习路线和方法

一些前端工程师面临的现状 1.没有系统的的学习基础知识 2.技术上存在短板,说句不好听的话,大多数开发者的上升通道都没有明确的路线,大公司还好,小公司基本都是后端作为开发组组长 3.前端各种技术层出不穷,需要花费…...

用C语言写一个自己的shell-Part Ⅱ--execute commands

Part Ⅱ–execute commands Exec This brings us to the exec family of functions. Namely, it has the following functions: execlexecvexecleexecveexeclpexecvp For our needs,we will use execvp whose signature looks like this int execvp(const char *file, cha…...

案例实践|运营腾讯游戏,Proxima Beta 使用 Apache Pulsar 升级团队协作与数据治理...

文章摘要本文整理自 Pulsar Summit Asia 2022 上,Proxima Beta 软件工程师施磊的分享《How to achieve better team integration and data governance by using Apache Pulsar》。本文首先将为大家介绍 CQRS 和 Event Sourcing 概念,便于了解为何 Proxim…...

Hudi的7种索引

1、Bloom Index Bloom Index (default) 使用根据记录键构建的bloom过滤器,也可以使用记录键范围修剪候选文件.原理为计算RecordKey的hash值然后将其存储到bitmap中,为避免hash冲突一般选择计算3次 HoodieKey 主键信息:主要包含recordKey 和p…...

Linux内核(十三)系统软中断 software

文章目录中断概述Linux内核中断软中断相关代码解析软中断结构体软中断类型软中断两种触发方式函数__do_softirq解析定时器的软中断实现解析定时器相关代码总结Linux版本:linux-3.18.24.x 中断概述 中断要求     快进快出,提高执行效率,…...

Linux -- 查看进程 PS 命令 详解

我们上篇介绍了, Linux 中的进程等概念,那么,在Linux 中如何查看进程呢 ??我们常用到的有两个命令, PS 和 top 两个命令,今天先来介绍下 PS 命令~!PS 命令 :作用 &#x…...

C2科一考试道路通行规定

目录 低能见度等恶劣环境下的通行规定 驾驶机动车禁止行为 停车规定 通行常识 高速公路限速规定 三观不一样的人,无论重来多少次,结果都一样 他不会懂你的委屈 只是觉得自已没错 两个人真正的可悲连吵架都不在一个点上 有句话说得好 我要是没点自我…...

进程概念(详细版)

进程的概念本文主要介绍进程的相关知识 文章目录认识冯诺依曼体系结构操作系统的基本概念操作系统的作用是什么系统调用和库函数相关概念进程基本概念描述进程进程控制块(PCB)task_struct 结构体进程是如何被操作系统管理起来的先描述再组织描述好,组织好&#xff0…...

学习大数据应该掌握哪些技能

想要了解大数据开发需要掌握哪些技术,不妨先一起来了解一下大数据开发到底是做什么的~ 1、什么是大数据? 关于大数据的解释,比较官方的定义是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模…...

【spring】Spring Data --Spring Data JPA

Spring Data 的委托是为数据访问提供熟悉且符合 Spring 的编程模型,同时仍保留着相关数据存储的特​​殊特征。 它使使用数据访问技术、关系和非关系数据库、map-reduce 框架和基于云的数据服务变得容易。这是一个伞形项目,其中包含许多特定于给定数据库…...

mysql数据库之视图

视图(view)是一种虚拟的存在,视图中的数据并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。 通俗的讲,视图之保存了查询的sql逻辑,不保存查询结…...

数据库事务详解

概述事务就是数据库为了保证数据的原子性,持久性,隔离性,一致性而提供的一套机制, 在同一事务中, 如果有多条sql执行, 事务可以确保执行的可靠性.数据库事务的四大特性一般来说, 事务是必须满足 4 个条件(ACID):原子性(Atomicity&…...

Nessus: 漏洞扫描器-网络取证工具

Nessue 要理解网络漏洞攻击,应该理解攻击者不是单独攻击,而是组合攻击。因此,本文介绍了关于Nessus历史的研究,它是什么以及它如何与插件一起工作。研究了Nessus的特点,使其成为网络取证中非常推荐的网络漏洞扫描工具…...

好的设计师网站有哪些/seo技术网网

对于单页应用,官方提供了vue-router进行路由跳转的处理,本篇主要也是基于其官方文档写作而成。安装基于传统,我更喜欢采用npm包的形式进行安装。npm install vue-router --save当然,官方采用了多种方式进行安装,包括bo…...

如何查询网站空间商/手游推广代理平台有哪些

今天介绍一下lamp环境的配置。 服务器用的是阿里云的服务器。 L:centos、A:apache、M:mysql、P:php (一)安装apache 我们这里安装的是httpd (1)安装httpd # yum install httpd…...

wordpress评论美化/如何做好精准营销

windows10下升级node.js和降级Nodejs_cheerileeyoki的博客-CSDN博客_win10 升级nodejs...

恩施市住房和城乡建设局网站/seo工具软件

闭包的优点,延长或扩大了变量的使用范围,延长了变量的使用时间,2.避免了变量命名的冲突 缺点:如果乱用闭包,会造成空间的浪费 创建person新实列:1创建一个新对象 2.将构造函数的作用域赋给新对象&#xff0…...

如何做网站咨询/免费b站推广网站短视频

目录:python学习目录 开发环境:vs 2019os.access(para1, para2) 用来判断para1路径有什么权限 para1:文件路径 para2:有以下四个值 os.F_OK:测试para1路径是否存在 os.R_OK:测试para1路径是否允许读 os.W_O…...

彩票网站做代理/网络营销的缺点及建议

首先查看配置内mysqlDriver 是否匹配: com.mysql.jdbc.Driver 是 mysql-connector-java 5中的,com.mysql.cj.jdbc.Driver 是 mysql-connector-java 6中的 其次查看pom内驱动是否版本对应、 mysql的版本对应jdbc驱动的版本 Connector/J 5.1 支持Mysql 4.…...