Estructura de datos subyacente del mapa de Golang
introducir
En el lenguaje de programación Golang, map
es una estructura de datos importante y de uso común. Proporciona una manera conveniente de almacenar y recuperar pares clave-valor. En este artículo, profundizaremos en golang
las map
estructuras de datos subyacentes para ayudarlo a comprenderlas y utilizarlas mejor.
map
conceptos básicos
map
Es un tipo de colección desordenada, que consta de pares clave-valor. Cada clave es única, mientras que los valores se pueden repetir. map
Se implementa en base a tablas hash, lo que hace que su rendimiento sea muy eficiente para la mayoría de operaciones.
map
La implementación subyacente de
En golang
, map
la estructura de datos subyacente es una tabla hash. La tabla hash consta de una matriz de depósitos y una lista vinculada de colisión hash. Cuando map
insertamos un par clave-valor en él, primero se calcula el valor hash de la clave y luego el par clave-valor se almacena en el depósito correspondiente.
Resolución de conflictos de hash
Debido a las limitaciones de las funciones hash, diferentes claves pueden producir el mismo valor hash, lo que se denomina colisión hash. En map
la implementación subyacente, se utiliza una lista vinculada para resolver el problema de los conflictos hash. Cuando ocurre una colisión de hash, se agrega un nuevo par clave-valor al encabezado de la lista vinculada.
map
operaciones de lectura y escritura
map
Las operaciones de lectura y escritura son muy eficientes. Al realizar una operación de búsqueda, primero se calcula el valor hash de la clave y luego se encuentra el depósito correspondiente a través del valor hash. Luego, realice una búsqueda lineal en la lista vinculada correspondiente al depósito para encontrar el par clave-valor correspondiente.
Cuando map
insertamos un par clave-valor en él, también se calcula el valor hash de la clave, se encuentra el depósito correspondiente y el nuevo par clave-valor se inserta al principio de la lista vinculada.
map
características de presentación
map
Sus características de rendimiento son las siguientes:
-
La complejidad temporal de la operación de lectura es O (1), que es un tiempo constante. -
La complejidad temporal de las operaciones de inserción y eliminación también es O (1). -
map
El tamaño cambia dinámicamente y se expandirá o reducirá automáticamente según sea necesario.
Precauciones
map
Hay varias cosas a tener en cuenta al usarlo :
-
map
Está desordenado, es decir, no hay garantía de que el orden de recorrido sea el mismo que el orden de inserción. -
map
的键必须是可比较的类型,例如int
、string
、float64
等,而值则可以是任意类型。 -
当通过键来访问 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 多平台发布