|
1 | 1 | --- |
2 | | -title: "Zig HashMap - 2" |
| 2 | +title: "HashMap 原理介绍下篇" |
3 | 3 | author: Wenxuan Feng |
4 | | -date: 2024-06-10T07:57:05.138Z |
| 4 | +date: 2024-06-11T07:57:06.138Z |
5 | 5 | --- |
6 | 6 |
|
7 | | -> 原文地址: https://www.openmymind.net/Zigs-HashMap-Part-2/ |
8 | | -
|
9 | | -# 正文 |
10 | | - |
11 | | -在[第一部分](https://www.openmymind.net/Zigs-HashMap-Part-1/)中,我们探讨了六种 `HashMap` 变体之间的关系以及每种变体为开发人员提供的不同功能。我们主要关注如何为各种数据类型定义和初始化 `HashMap`,并讨论了当 `StringHashMap` 或 `AutoHashMap` 不支持的类型时使用自定义 `hash` 和 `eql` 函数的重要性。在这篇文章中,我们将更深入地研究键和值的存储、访问方式以及我们在它们生命周期管理中的责任。 |
| 7 | +在[第一部分](/post/2024/06/10/zig-hashmap-1/)中,我们探讨了六种 `HashMap` 变体之间的关系以及每种变体为开发人员提供的不同功能。我们主要关注如何为各种数据类型定义和初始化 `HashMap`,并讨论了当 `StringHashMap` 或 `AutoHashMap` 不支持的类型时使用自定义 `hash` 和 `eql` 函数的重要性。在这篇文章中,我们将更深入地研究键和值的存储、访问方式以及我们在它们生命周期管理中的责任。 |
12 | 8 |
|
13 | 9 | Zig 的哈希表内部采用两个切片结构:一个用于存放键(key),另一个用于存储对应的值(value)。通过应用哈希函数计算得到的哈希码被用来在这些数组中定位条目。从基础代码出发,比如: |
14 | 10 |
|
@@ -43,7 +39,7 @@ keys: values: |
43 | 39 |
|
44 | 40 | 这个基本的可视化表示将贯穿本文大部分内容,并且不断强调条目的位置需要保持一致性和可预测性。即使哈希表需要在增长时从一个底层数组移动到另一个(即当填充因子达到一定阈值并要求扩大以容纳更多数据时),这一事实是我们将反复回顾的主题。 |
45 | 41 |
|
46 | | -## 值管理 |
| 42 | +# 值管理 |
47 | 43 |
|
48 | 44 | 如果我们对上述代码片段进行扩展,并调用 `lookup.get("Paul")`,返回的值将是 `1234`。在处理像 `i32` 这样的原始类型时,很难直观地理解 `get` 方法和它的可选返回类型 `?i32` 或更通用的 `?V`(其中 `V` 表示任何值类型)之间的区别。考虑到这一点,让我们通过替换 `i32` 为一个封装了更多信息的 `User` 类型来展示这一概念: |
49 | 45 |
|
@@ -224,7 +220,7 @@ while (it.next()) |value_ptr| { |
224 | 220 |
|
225 | 221 | 在最后一种情况下,由于我们存储的是 `User` 而不是 `*User`,我们的 `value_ptr` 是指向 `User` 的指针(不像之前那样是指向指针的指针)。 |
226 | 222 |
|
227 | | -## Keys |
| 223 | +# Keys |
228 | 224 |
|
229 | 225 | 我们可以开始和结束这一节:我们关于值的所有内容同样适用于键。这是100%正确的,但这在某种程度上不太直观。大多数开发人员很快就能理解,存储在哈希表中的堆分配的 `User` 实例有其自身的生命周期,需要显式管理/释放。但由于某些原因,这对于键来说并不那么明显。 |
230 | 226 |
|
@@ -337,7 +333,7 @@ if (lookup.fetchRemove(user.name)) |kv| { |
337 | 333 |
|
338 | 334 | 对于大多数情况,在处理非原始键或值时,关键是当你调用哈希表的 `deinit` 时,你为键和值分配的任何内存不会被自动释放;你需要自己处理。 |
339 | 335 |
|
340 | | -## getOrPut |
| 336 | +# getOrPut |
341 | 337 |
|
342 | 338 | 虽然我们已经讨论过的内容有很多含义,但对我来说,直接暴露键和值指针的最大好处之一是 `getOrPut` 方法。 |
343 | 339 |
|
@@ -367,6 +363,8 @@ if (gop.found_existing) { |
367 | 363 |
|
368 | 364 | 当然,只要不对哈希表进行修改,`value_ptr` 就应被视为有效。顺便提一句,这同样适用于我们通过 `iterator()`、`valueIterator` 和 `keyIterator` 获取的迭代键和值,原因相同。 |
369 | 365 |
|
370 | | -## 结论 |
| 366 | +# 结论 |
371 | 367 |
|
372 | 368 | 希望你现在对使用「std.HashMap」、「std.AutoHashMap」和「std.StringHashMap」以及它们的「unmanaged」变体感到更加得心应手。虽然你可能永远不需要提供自己的上下文(例如「hash」和「eql」函数),但了解这是一个选项是有益的。在日常编程中,可视化数据尤其有用,尤其是在使用指针和添加间接层次时。每当我处理 `value_ptr` 或 `key_ptr` 时,我都会想到这些切片以及值或键与这些切片中值或键的实际地址之间的区别。 |
| 369 | + |
| 370 | +> 原文地址: https://www.openmymind.net/Zigs-HashMap-Part-2/ |
0 commit comments