起因
为了降低并发时的API请求量, 这两天写了个LRU Cache. 其中用到了Set做AllowList, 来判断API是否应该被缓存.
在MDN查API时, 发现Set被归类在Keyed Collection中. 一直以来, 下意识觉得Set只是value唯一的Array. 应该属于Indexed Collection. 感觉有些奇怪, 所以就查了下Set的实现机制
过程
一开始, 先去MDN查的文档, 只说了属于Keyed Collection, 但没细说为什么. 又去ecma-international.org, 查ECMA标准, 结果也没有明确说明, 为什么Set属于Keyed Collection. 我一开始还觉得是文档写得不够详细, 后来发现是自己太菜了😂
简单思考了下, 没想通. 就使用魔法武器了. 虽然有点前后不一, 但copilot提供了最关键的信息: Hash Table. 下边是copilot的回答
在 JavaScript 中,Set 是一种基于哈希表实现的数据结构,用于存储一组唯一的值。Set 属于 ECMAScript 6 中新增的数据类型之一,被归类为 Keyed Collection 类型。
Keyed Collection 是 ECMAScript 6 中新增的一种数据类型,用于存储一组键值对。除了 Set 之外,还包括 Map 和 WeakMap。这些数据类型都具有以下特点:
- 可以使用任意类型的值作为键。
- 可以使用 for…of 循环遍历键值对。
- 可以使用 size 属性获取键值对的数量。
Set 作为 Keyed Collection 的一种,可以使用任意类型的值作为元素,而且每个元素都是唯一的。因此,Set 可以用于实现集合、过滤重复值等功能。
需要注意的是,Set 和 Map 的实现方式不同,虽然它们都属于 Keyed Collection 类型。Map 是一种键值对的集合,其中每个键都是唯一的,可以使用键来访问对应的值。Set 是一种值的集合,其中每个值都是唯一的,可以使用值来访问对应的值。
再然后, 就破案了… 因为Hash Table中, 每个元素都有唯一的key, 用key来访问对应的值. 所以, Set相当于一个key-value相同的、特殊的Hash Table, 我认为也可以理解为, 一种key-value一致、特殊的Map
结论
- Set是基于Hash Table实现的「值的集合」
- 由于Hash Table的key-value特性, Set的key-value相同
- Set相当于一种特殊的Map
所以, Set属于Keyed Collection
┌─────┐
┌─▶│Array│
┌──────────────────┐ │ └─────┘
┌─▶│Indexed Collection│──┤
│ └──────────────────┘ │ ┌───────────┐
│ └─▶│Typed Array│
│ └───────────┘
┌────────────┐ │
│ Collection │──┤ ┌───┐ *
└────────────┘ │ ┌─▶│Map│ *
│ │ └───┘ *
│ │ ┌───────┐ *
│ ┌──────────────────┐ ├─▶│WeakMap│ * ┌───────────────────┐
└─▶│ Keyed Collection │──┤ └───────┘ * │Based on Hash Table│
└──────────────────┘ │ ┌───┐ * └───────────────────┘
├─▶│Set│ *
│ └───┘ *
│ ┌───────┐ *
└─▶│WeakSet│ *
└───────┘ *
资料
- https://262.ecma-international.org/13.0/#sec-keyed-collections
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Keyed_collections#key_and_value_equality_of_map_and_set