Map、Dictionary、Hash Table:到底该用哪一个?

发布于:2025-08-18 ⋅ 阅读:(19) ⋅ 点赞:(0)

开场白

面试常问,代码常写,Google 常搜。
“Map、Dictionary、Hash Table 有啥区别?”
今天用一篇博客讲透:它们分别活在哪一层、各有什么超能力,以及——真正写代码时怎么选


1. Hash Table(哈希表)

1.1 定义

最底层的数据结构:数组 + Hash 函数 + 冲突解决策略(Separate Chaining / Open Addressing / Robin-Hood…)。

1.2 超能力

  • 均摊时间复杂度 O(1):增、删、查。

  • 内存紧凑:指针可控、Cache-Friendly。

  • 可高度定制:开放地址省指针,Robin-Hood 省 CPU Cache Miss。

1.3 适用场景

  • 写底层库:Redis dict、Linux 路由表、数据库索引。

  • 性能极限场景:游戏引擎 ECS、高频交易系统撮合引擎。
    一句话:当你需要“把哈希函数握在自己手里”时,选 Hash Table。


2. Dictionary(字典)

2.1 定义

各大语言标准库对“基于 Hash Table 的键值容器”的统称:

  • C# Dictionary<TKey,TValue>

  • Python dict

  • Swift Dictionary<Key, Value>

2.2 超能力

  • 开箱即用get / set / remove / ContainsKey 一套带走。

  • 键类型 = 可哈希且可相等(string、number、enum…)。

  • 无序:语义上不保证遍历顺序(Python 3.7+ 只是实现细节)。

2.3 适用场景

99% 的业务代码都适合:

  • 根据 userId 找用户

  • 根据枚举值拿配置

  • 缓存序列化结果、计数器
    一句话:不想造轮子,只想把键值塞进一个黑盒,用 Dictionary。


3. Map(映射)

3.1 定义

ES6 / Java / TypeScript 中的“高配”键值容器。

3.2 超能力

  • 键可以是任意类型:对象、Symbol、函数、NaN。

  • 记住插入顺序:天然可迭代,for…of 顺序稳定。

  • size 直读:不用 Object.keys(obj).length

  • 弱引用版本WeakMap 防内存泄漏。

3.3 适用场景

  • 键必须是 DOM 节点 / 对象 / Symbol(事件总线、元数据挂载)。

  • 需要 稳定顺序(LRU Cache、插件加载顺序)。

  • 高频增删且不想踩 __proto__ 坑。
    一句话:当 Dictionary 的键类型或顺序限制让你抓狂,上 Map。


4. 横向对比表(收藏级)

表格

复制

维度 Hash Table Dictionary Map
抽象层级 数据结构裸实现 标准库封装 标准库高配封装
键类型限制 自己定 可哈希标量 任意类型
插入顺序 无保证 无保证 保留
时间复杂度 O(1) 均摊 O(1) 均摊 O(1) 均摊(略慢,可忽略)
API 丰富度 0(自己写) 中等 高(迭代器、WeakMap)
业务代码开闭原则 ❌ 开 ✅ 闭 ✅ 闭
典型用途 写底层、性能极限 99% 业务键值存储 对象键 / 顺序敏感

5. 一句话选型口诀(背下来)

  • 键是字符串 / 数字?Dictionary

  • 键是对象 / Symbol / 要顺序?Map

  • 需要魔改哈希函数、榨干最后一滴性能?Hash Table


6. 彩蛋:代码片段对照

// Dictionary 写法(TypeScript)
const users: Record<string, User> = {};

// Map 写法(TypeScript)
const usersMap = new Map<string, User>();

// 自己撸 Hash Table(C 伪代码)
struct Entry { char* key; void* val; };
Entry table[1024];
uint32_t hash(char* k) { /* djb2 */ }

如果这篇博客帮你在面试或 CR 中少吵一次架,点个 👍 再走吧!


网站公告

今日签到

点亮在社区的每一天
去签到