1. 引言

map 是 Go 语言中使用频率极高的数据结构,它提供了快速的键值对存取能力。虽然 map 的使用非常简单,但其底层的实现却是一个精心设计的哈希表,它需要高效地处理哈希计算、数据存储、扩容以及最关键的——哈希冲突。

本文将解剖 map 的底层数据结构,详细阐述其查找、赋值和扩容过程,特别是它是如何解决哈希冲突的。

2. map 的核心数据结构

Go map 的运行时表示是 runtime.hmap 结构体,其关键字段如下:

// src/runtime/map.go
type hmap struct {count     int    // map 中元素的个数,即 len(m)flags     uint8B         uint8  // buckets 的对数,buckets 数量 = 2^Bnoverflow uint16 // 溢出桶的大致数量hash0     uint32 // 哈希种子buckets    unsafe.Pointer // 指向 bucket 数组的指针,大小为 2^Boldbuckets unsafe.Pointer // 在扩容时,指向旧的 bucket 数组nevacuate  uintptr        // 扩容进度计数器// ...
}

map 的核心是一个 bucket 数组。每个 bucket 是一个 runtime.bmap 结构:

// 一个 bucket 最多可以存放 8 个键值对
const bucketCnt = 8type bmap struct {tophash [bucketCnt]uint8 // 存储每个 key 哈希值的高 8 位// keys and values follow
}
  • B: 决定了 map 有多少个 bucket,总数是 2B。

  • buckets: 是一个指针,指向一个连续的 bucket 数组。

  • bmap (bucket):

    • tophash: 这是一个巧妙的优化。它存储了每个 key 的哈希值的高 8 位 (top hash)。在查找 key 时,可以先快速比较这 8 位,如果 tophash 都不匹配,就无需再比较完整的 key,从而加速查找。

    • 键和值: bmap 结构体之后,紧跟着存储了 8 个 key 和 8 个 value。它们在内存上是连续的。

  • 溢出桶 (Overflow Bucket): 如果一个 bucket 的 8 个槽位都满了,map 会通过一个指针将这个 bucket 与一个溢出桶链接起来,形成一个链表。

3. map 的工作流程
a) 写入/赋值 (map[key] = value)
  1. 哈希计算: 使用哈希函数计算 key 的哈希值 hash

  2. 定位 Bucket: 使用 hash低 B 位来决定这个 key 应该落在哪个 bucket 中。例如,bucketIndex = hash & (2^B - 1)

  3. 定位槽位:

    • 计算 hash高 8 位 tophash

    • 遍历目标 bucket 的 tophash 数组,看是否存在相同的 tophash

    • 如果 tophash 相同,再完整地比较 key 是否相同。

    • 如果 key 已存在,则更新对应的 value

    • 如果 key 不存在,就在 bucket 中找一个空槽位,存入 tophash, keyvalue

  4. 处理冲突与溢出: 如果当前 bucket 的 8 个槽位都满了,map 会创建一个新的溢出桶,并让当前 bucket 指向它。新的键值对将被存入这个溢出桶。

b) 查找 (value, ok := map[key])

查找过程与写入类似。通过哈希值定位到 bucket,然后先比较 tophash,再比较完整的 key。会依次遍历 bucket 和其所有链接的溢出桶,直到找到 key 或者遍历完所有溢出桶。

c) 扩容 (Grow)

当以下任一条件满足时,map 会触发扩容:

  1. 负载因子超限: map 中元素的数量 count / bucket 数量 2^B > 6.5。

  2. 溢出桶过多: map 的溢出桶数量过多时(当 B < 15 时,noverflow >= 2^B),也会触发扩容,这主要是为了解决因大量删除操作导致的内存空洞问题。

扩容方式:

  • 等量扩容: 如果是因溢出桶过多触发,map 会创建一个与原 bucket 数组大小相同的新数组,然后将数据重新排列(rehash),目的是消除内存碎片。

  • 翻倍扩容: 如果是因负载因子超限触发,map 会创建一个两倍大的 bucket 数组(B 会加 1)。

渐进式扩容 (Incremental Evacuation): 为了避免因扩容导致长时间的 STW,Go map 的扩容是渐进式的。

  • 扩容时, map 不会一次性将所有数据从 oldbuckets 搬到 buckets

  • 而是每当对 map 进行一次写入或删除操作时,会顺便“搬运”一到两个 bucket 的数据。

  • 查询操作可能会同时在 oldbucketsbuckets 中进行。

  • 整个搬运过程会分散到多次操作中,直到 oldbuckets 中的数据全部迁移完毕。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/91551.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/91551.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/91551.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Reinforcing General Reasoning without Verifiers

1.概述 DeepSeek-R1-Zero [10] 最近展示了使用可验证奖励的强化学习(RL)训练大型语言模型(LLMs)可以极大地提高推理能力。在这个可验证奖励的强化学习(RLVR)框架 [17] 中,LLM 生成一个推理过程(即,思维链,CoT),然后给出最终答案。一个基于规则的程序随后提取并评估…

Hyperbrowser MCP:重新定义网页抓取与浏览器自动化的AI驱动工具

在数据驱动的时代,网页内容的高效处理和自动化操作成为开发者和企业关注的焦点。Hyperbrowser MCP(Model Context Protocol Server)作为一款革命性的工具,通过AI与浏览器技术的深度融合,为网页抓取、结构化数据提取和浏览器自动化提供了全新的解决方案。无论你是需要从复杂…

关于Web前端安全防御XSS攻防的几点考虑

作为一位前端老鸟&#xff0c;总结一下web前端安全领域基础概念、防御策略、框架实践及新兴技术等几个维度的考虑。一、基础概念与核心漏洞1.XSS 攻击XSS&#xff08;跨站脚本攻击&#xff09;是 Web 前端安全中最常见的威胁之一&#xff0c;其核心是攻击者将恶意脚本注入到网页…

eSIM技术深度解析:从物理芯片到数字革命

当苹果公司在2018年首次在iPhone XS系列中引入eSIM技术时&#xff0c;许多用户可能并未意识到这个看似微小的改变将带来怎样的技术革命。从1991年第一张信用卡大小的SIM卡&#xff0c;到今天仅有5mm x 5mm的eSIM芯片&#xff0c;这不仅仅是尺寸的缩小&#xff0c;更是移动通信技…

通俗易懂解释Java8 HashMap

我们来用通俗易懂的方式解释一下 Java 8 中 HashMap 的原理&#xff0c;让你对它的结构、运行机制有清晰的理解。&#x1f333; 什么是 HashMap&#xff1f; HashMap 是 Java 中非常常用的数据结构&#xff0c;用于存储键值对&#xff08;key-value&#xff09;。你可以把它理解…

macOS安装配置Unbound DNS完整指南

文章目录macOS安装配置Unbound DNS完整指南&#x1f3af; 为什么选择Unbound&#xff1f;&#x1f4cb; 系统要求&#x1f680; 安装步骤1. 使用Homebrew安装2. 查看安装信息⚙️ 基础配置1. 备份默认配置2. 创建基础配置文件3. 基础配置内容配置53端口版本&#xff08;高级用户…

学习模板元编程(2)std::true_type/false_type

目录 实现原理 应用场景 条件编译 通过特化和继承&#xff0c;实现std::is_xxx系列 思路 举例 例子1&#xff0c;is_bool 例子2&#xff0c;is_ptr 实现原理 std::true_type/false_type是模板intergral_constant的两种实现&#xff1a; using true_type integral_co…

Chain-of-Thought Prompting Elicits Reasoning in Large Language Models论文阅读笔记

Chain-of-Thought Prompting Elicits Reasoning in Large Language Models 摘要 本文探索了思维链&#xff08;chain of thought&#xff09;&#xff0c;即一系列中间推理过程&#xff0c;可以有效地增强大语言模型的复杂推理能力。 在三个大型语言模型上的实验表明&#xff0…

华为核心交换机S7700的内存OID

华为S7700系列交换机 SNMP内存相关OID说明 以下列出了华为S7700核心交换机在SNMP v2c下可用的内存相关OID,包括CPU内存利用率、物理内存总量、已用内存和空闲内存,并给出每个OID的功能描述、数据类型、单位、使用说明等信息。 1. CPU内存利用率(处理器内存占用百分比) OID名…

中州养老Day02:服务管理护理计划模块

本日任务:服务管理的后端开发 1.学习:护理项目 (1)评估开发工期的思路和注意事项 全面熟悉项目,了解项目重点,设置开发优先级 比如,在下面图片的接口文档中版本有1.0,2.0,3.0也就是功能的初代,二代,三代,所以我们在大致浏览所有功能后,要优先关注初代功能的实现 开发计划 …

JavaScript:Ajax(异步通信技术)

一、Ajax 核心概念Ajax&#xff08;Asynchronous JavaScript and XML&#xff09;是一种异步通信技术&#xff0c;核心特点&#xff1a;无刷新更新&#xff1a;无需重新加载整个页面异步处理&#xff1a;后台发送/接收数据不阻塞用户数据格式&#xff1a;支持 XML/JSON/HTML/纯…

leetcode 118. 杨辉三角 简单

给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。示例 1:输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]示例 2:输入: numRows 1 输出: [[1]]提示:1 < numRows…

jmeter--While控制器--循环直到接口响应符合条件

场景描述业务场景&#xff1a;单据计算接口情况&#xff1a;单据计算&#xff0c;调用接口1发起计算&#xff0c;接口2查询计算执行结果jmeter脚本&#xff1a;把接口1和接口2&#xff08;接口2循环调用&#xff0c;直到返回执行完成状态&#xff09;添加到一个事务&#xff0c…

组播 | 不同 VLAN 间数据转发实现逻辑 / 实验

注&#xff1a;本文为 “不同 vlan 间组播数据转发” 相关合辑。 图片清晰度受引文原图所限。 略作重排&#xff0c;如有内容异常&#xff0c;请看原文。 组播 VLAN&#xff1a;解决路由器为不同 VLAN 用户复制多份流量问题 aiaiai010101 于 2018-11-16 22:42:06 发布 一、组…

渗透测试常用指令

互联网设备的开放信息查询网站&#xff1a; https://fofa.info/ https://www.zoomeye.org/ https://quake.360.net/quake/#/index https://x.threatbook.com/v5/mapping https://hunter.qianxin.com/ 目录 一、网络探测与扫描 traceroute whatweb ping fping nc n…

51单片机串行通信的设计原理有哪些?

51单片机是指由美国INTEL公司生产的一系列单片机的总称&#xff0c;这一系列单片机包括了许多品种&#xff0c;如8031&#xff0c;8051&#xff0c;8751&#xff0c;8032&#xff0c;8052&#xff0c;8752等&#xff0c;其中8051是最早最典型的产品&#xff0c;该系列其它单片机…

设计模式十四:适配器模式(Adapter Pattern)

适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;用于将一个类的接口转换成客户端期望的另一个接口&#xff0c;使原本不兼容的类可以一起工作。适配器模式的类型类适配器&#xff08;通过多重继承实现&#xff09;对象适配器&#xff08;通…

力扣经典算法篇-38-组合(回溯算法)

1、题干 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;n 4, k 2 输出&#xff1a; [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ] 示例 2&#xff1a; 输入&#xff1a;…

多人命题系统

目 录 摘 要 Abstract 1 系统概述 1.1 概述 1.2课题意义 1.3 主要内容 2 系统开发环境 2. 1 JAVA简介 2. .2 B/S架构 2.3 SSM三大框架 2.4访问数据库实现方法 2.5 系统对MySQL数据库的两种连接方式 3 需求分析 3.1技术可行性&#xff1a;技术背景…

UDP_千兆光通信(四)Tri Mode Ethernet MAC ip核

Tri Mode Ethernet MAC ip核使用与例程分析 一、 Tri Mode Ethernet MAC ip核功能 二、 Tri Mode Ethernet MAC ip核配置 数据传输速率 主要设置接口 帧滤波功能选择,以及流控选择 三、 Tri Mode Ethernet MAC ip核使用 3.1 ip核接口 3.2 ip核接口说明 3.2.1 tx_ifg_delay 3.2…