golang之map介绍

golang的map底层数据结构

介绍

在Golang编程语言中,map是一种重要且常用的数据结构。它提供了一种方便的方式来存储和检索键值对。在本篇文章中,我们将深入探讨golangmap的底层数据结构,以帮助您更好地理解和使用它。

map的基本概念

map是一种无序的集合类型,它由键值对组成。每个键都是唯一的,而值则可以重复。map是基于哈希表实现的,这使得对于大多数操作,其性能都非常高效。

map的底层实现

golang中,map的底层数据结构是一个哈希表。哈希表由一个桶(bucket)数组和哈希冲突链表组成。当我们向map中插入一个键值对时,首先会计算键的哈希值,然后将该键值对存储在对应的桶中。

哈希冲突解决

由于哈希函数的限制,不同的键可能会产生相同的哈希值,这就是所谓的哈希冲突。在map的底层实现中,使用了链表来解决哈希冲突的问题。当发生哈希冲突时,新的键值对会被添加到链表的头部。

map的读写操作

map的读写操作都是非常高效的。在进行查找操作时,首先会计算键的哈希值,然后通过哈希值找到对应的桶。接着,再在该桶对应的链表中进行线性查找,找到对应的键值对。

当我们向map中插入一个键值对时,同样会计算键的哈希值,找到对应的桶,并在链表的头部插入新的键值对。

map的性能特点

map的性能特点如下:

  • 读取操作的时间复杂度为O(1),即常数时间。
  • 插入和删除操作的时间复杂度也为O(1)。
  • map的大小是动态变化的,它会根据需要自动扩容或缩容。

注意事项

在使用map时,有几个需要注意的事项:

  1. map是无序的,即无法保证遍历的顺序与插入的顺序相同。
  2. map的键必须是可比较的类型,例如 intstringfloat64等,而值则可以是任意类型。
  3. 当通过键来访问 map中的值时,如果该键不存在, map会返回值类型的零值。

源码解析

runtime/map.go

map的底层数据结构源码位于runtime/map.go文件中。在该文件中,定义了hmap结构体,它表示map的底层哈希表。

type hmap struct {
    
    
    count     int
    flags     uint8
    B         uint8
    noverflow uint16
    hash0     uint32

    buckets    unsafe.Pointer
    oldbuckets unsafe.Pointer
    nevacuate  uintptr
    extra      *mapextra
}

哈希表的桶结构

哈希表的桶结构定义如下:

type bmap struct {
    
    
    tophash [bucketCnt]uint8
    keys    [bucketCnt]keytype
    values  [bucketCnt]valuetype
}

其中,tophash数组存储了每个键值对的哈希值的低8位,用于快速定位桶中的键值对。keys数组和values数组分别存储了键和值的实际数据。

哈希冲突解决

map的哈希表中,当多个键的哈希值相同时,会发生哈希冲突。为了解决哈希冲突,Golang采用了链地址法。每个桶的tophash数组中的元素存储了相同哈希值的键值对在链表中的位置。

数据访问和修改

在访问map的键值对时,首先会通过哈希函数计算键的哈希值,然后根据哈希值找到对应的桶。接着,在桶的链表中进行线性查找,找到目标键值对。

当向map中插入新的键值对时,会按照相同的过程计算哈希值,并将键值对插入到对应的桶中。

扩容和缩容

map的大小是动态变化的。当map中的键值对数量达到一定阈值时,会触发扩容操作。扩容操作会创建一个新的哈希表,并将原有的键值对重新分配到新的桶中。

相反,当键值对的数量减少时,也可能触发缩容操作。缩容操作会将键值对重新分配到更小的哈希表中。

写在最后

感谢大家的阅读,晴天将继续努力,分享更多有趣且实用的主题,如有错误和纰漏,欢迎给予指正。 更多文章敬请关注作者个人公众号 晴天码字

本文由 mdnice 多平台发布

猜你喜欢

转载自blog.csdn.net/all_about_WZY/article/details/131371540