【Go语言从新手到高手】初阶篇-第3章 数据类型 3.3 映射(map)

3.3.1 map的声明与初始化

什么是map?

Go语言中的map是一种无序的键值对集合,类似于其他语言中的字典或哈希表。map的键必须是可比较的类型,比如字符串、整数等。值可以是任意类型。

Go 语言 map 的底层实现

Go 语言中的 map 底层实现是一个哈希表。哈希表是一种通过哈希函数将值映射到特定的索引位置的数据结构,从而实现快速查找。Go 的 map 实现经过了精心的设计,具有高效的性能和良好的并发安全性。

hmap 结构体

Go map 的底层数据结构是 hmap 结构体。这个结构体包含了 map 的所有元数据,包括:

  • 计数器: 记录 map 中的元素个数、扩容次数等。
  • 桶数组: 一个指向桶数组的指针。每个桶存储多个键值对。
  • 溢出桶: 当桶中的元素过多时,会将多余的元素放到溢出桶中。
  • 加载因子: 用于判断是否需要扩容。
  • 哈希种子: 用于计算哈希值。

工作原理

  1. 哈希计算: 当向 map 中插入一个键值对时,首先会根据键的哈希值计算出该键应该存储在哪个桶中。
  2. 桶内查找: 在指定的桶中,通过比较键的哈希值和相等性来查找对应的键值对。如果找到,则更新值;否则,插入新的键值对。
  3. 扩容: 当 map 中的元素数量超过了某个阈值时,会触发扩容操作。扩容过程会创建一个新的、更大的桶数组,并将旧桶数组中的元素重新散列到新桶数组中。

核心概念

  • 桶 (bucket): map 的底层存储单元,每个桶可以存储多个键值对。
  • 溢出桶: 当桶中的元素过多时,会将多余的元素放到溢出桶中,以避免单个桶过大。
  • 加载因子: 用于判断 map 是否需要扩容。当元素数量超过加载因子乘以桶数量时,就会触发扩容。
  • 哈希冲突: 当两个不同的键计算出相同的哈希值时,就会发生哈希冲突。Go map 使用开放寻址法来解决哈希冲突,即在同一个桶中线性探测下一个空闲位置。

优点

  • 高效: 哈希表的查找、插入和删除操作的时间复杂度通常为 O(1)。
  • 灵活: 可以存储任意类型的键值对。
  • 并发安全: Go 的 map 在多协程并发访问时是安全的。

map的声明与初始化

  1. 声明一个map
var myMap map[string]int
  • map[string]int: 表示这是一个键为字符串,值为整型的map。
  1. 初始化一个map
  • 使用make函数:
myMap := make(map[string]int)

make函数用来分配内存并初始化map。

  1. 初始化并赋值:
myMap := map[string]int{
   "apple": 5, "banana": 3}

直接在声明时初始化并赋值。

map的常用操作

  • 添加元素:
map[key] = value
  • 访问元素:
value := map[key]
  • 判断key是否存在:
value, ok := map[key]
  • 删除元素:
delete(map, key)
  • 遍历map: 使用 for range 循环。

3.3.2 添加、删除与更新键值对

1. 添加键值对

在 Go 语言中,向 map 添加键值对非常直观:

package main

import "fmt"

func main() {
   
    // 创建一个空的字符串到整型的 map
    myMap := make(map[string]int)

    // 添加键值对
    myMap["apple"] = 5
    myMap[
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鱼弦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值