Set 和 Map 是 ES6 引入的两种新数据结构,它们在用途和特性上有明显区别:
1. 核心区别
| 特性 | Set | Map |
|---|---|---|
| 存储内容 | 值的集合 | 键值对的集合 |
| 元素唯一性 | 值唯一 | 键唯一(值可以重复) |
| 查找方式 | 直接通过值查找 | 通过键查找对应的值 |
| 默认迭代 | 返回 [value, value] |
返回 [key, value] |
| 典型用途 | 去重、成员检查 | 数据映射、字典、缓存 |
2. 详细对比
Set(集合)
js
const set = new Set();
set.add(1);
set.add(2);
set.add(2); // 重复值不会被添加
console.log(set.size); // 2
console.log(set.has(1)); // true
set.forEach(value => console.log(value)); // 1, 2
// 去重示例
const arr = [1, 2, 2, 3, 3];
const unique = [...new Set(arr)]; // [1, 2, 3]
Map(映射)
js
const map = new Map();
map.set('name', 'Alice');
map.set('age', 25);
map.set('age', 26); // 更新键'age'的值
console.log(map.size); // 2
console.log(map.get('name')); // 'Alice'
console.log(map.has('age')); // true
for (let [key, value] of map) {
console.log(key, value); // 'name Alice', 'age 26'
}
3. 选择使用场景
使用 Set 的场景:
- 数组去重
- 检测元素是否存在于集合中
- 数学中的集合运算(并集、交集、差集)
- 存储唯一标识符列表
使用 Map 的场景:
- 需要键值对存储,且键不是字符串
- 需要维护键的插入顺序
- 缓存数据(键值映射)
- 需要频繁增删键值对
- 对象作为键的情况
4. 共同特点
js
// 1. 都维护插入顺序
const set = new Set();
set.add(1).add(3).add(2);
[...set]; // [1, 3, 2] - 保持插入顺序
const map = new Map();
map.set('a', 1).set('c', 3).set('b', 2);
[...map.keys()]; // ['a', 'c', 'b'] - 保持插入顺序
// 2. 性能相似
// 查找、添加、删除的时间复杂度都是 O(1)
// 都比 Object 更适合频繁增删的场景
// 3. 相同的迭代方法
// keys(), values(), entries(), forEach()
5. 与 Object 的对比
Map 优于 Object 的情况:
js
// 1. 键可以是任意类型
const map = new Map();
const objKey = { id: 1 };
map.set(objKey, 'value'); // ✅ 允许对象作为键
map.set(NaN, 'number'); // ✅ 允许NaN作为键
// 2. 可以直接获取大小
map.size; // ✅ 直接获取
Object.keys(obj).length; // ❌ 需要计算
// 3. 迭代更友好
for (let [key, value] of map) { ... } // ✅
Set 优于 Array 的情况:
js
// 1. 去重和查找性能更好
set.has(value); // O(1)
array.includes(value); // O(n)
// 2. 删除元素更高效
set.delete(value); // O(1)
array.splice(index, 1); // O(n)
6. 互相转换示例
js
// Map ↔ Array
const map = new Map([['a', 1], ['b', 2]]);
const arr = [...map]; // [['a', 1], ['b', 2]]
const map2 = new Map(arr);
// Set ↔ Array
const set = new Set([1, 2, 3]);
const arr2 = [...set]; // [1, 2, 3]
const set2 = new Set(arr2);
// Map ↔ Object
const obj = Object.fromEntries(map); // {a: 1, b: 2}
const map3 = new Map(Object.entries(obj));
总结
- Set 是值的集合,用于处理唯一值场景
- Map 是键值对集合,用于建立映射关系
- 两者都保持插入顺序,都有 O(1) 的查找性能
- 选择依据:是否需要存储键值对关系,还是只需要存储独立的值