Map 和 Set 是 ES6 提供的哈希表实现数据结构,查找、插入、删除平均时间复杂度均为 O(1);Set 用于存储唯一值,支持任意类型键和快速存在性判断;Map 支持任意类型键的键值对存储,保持插入顺序且避免原型污染。

Map 和 Set 是 ES6 引入的原生数据结构,专为解决传统对象和数组在存储与检索上的短板而设计。它们底层采用哈希表实现,查找、插入、删除平均时间复杂度都是 O(1),比数组遍历(O(n))或对象属性访问(受原型链、字符串键限制)更高效、更可靠。
Set:唯一值的高效容器
Set 适合管理“不重复的一组值”,核心优势在于自动去重 + 快速存在性判断。
-
去重操作极简:数组去重只需一行
[...new Set(arr)],比 filter + indexOf 或 includes 高效得多,尤其在大数据量时差异明显 -
存在性检查更快:
set.has(x)是常数时间查找;而数组用arr.includes(x)或arr.indexOf(x) !== -1需逐项扫描 -
支持任意类型值:数字、字符串、布尔值、NaN(Set 中 NaN 被视为相等)、对象引用都能存,且用 SameValueZero 算法比较(
NaN === NaN成立) - 保持插入顺序:遍历时按添加顺序返回,不像老式对象属性顺序不可靠
Map:任意键型的有序键值对存储
Map 解决了普通对象“键只能是字符串或 Symbol”“易受原型污染”“无内置 size 属性”等问题,特别适合需要非字符串键或精确控制键值行为的场景。
-
键可以是任何类型:用对象、函数、甚至另一个 Map 作键都合法,且能正确区分不同引用(
map.set({}, 'a'); map.get({})返回 undefined,因为两个空对象不是同一引用) - 插入顺序严格保留:for-of、keys()、values()、entries() 都按写入顺序迭代,语义清晰可预测
-
操作接口统一高效:
map.set(k, v)、map.get(k)、map.has(k)、map.delete(k)全部是 O(1) 平均复杂度 - 天然支持统计与缓存:比如用 DOM 元素作键缓存计算结果,或用函数作键映射配置,避免字符串序列化/反序列化开销
实际使用中的关键细节
高效不只是用对 API,还要避开常见误区:
-
别把 Set 当数组用:它没有索引、不支持
push/pop,想随机访问或按位置操作,先转成数组Array.from(set) - Map 的键比较基于引用而非内容:对象键必须复用同一引用才能 get 到值;若需按内容匹配,考虑用 JSON.stringify 或自定义 key 生成逻辑
-
初始化优先传入可迭代结构:如
new Set([1,2,2,3])或new Map([['a',1],['b',2]]),比循环 add/set 更简洁且性能略优 -
size 属性直接可用:Set 用
set.size,Map 用map.size,无需Object.keys(obj).length这类间接计算
什么时候该选哪个?
一句话判断:
- 只关心“有没有这个值”,不关心“它对应什么” → 用 Set(如权限列表、已加载资源 ID、用户标签集合)
- 需要“通过某个东西查到另一样东西”,且键不一定是字符串 → 用 Map(如组件实例映射状态、URL 参数解析结果、事件监听器注册表)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











