Set和Map有什么区别?

简介: Set和Map有什么区别?

在 JavaScript 中,SetMap 是两种常用的集合类型,它们都用于存储数据,但设计目的和应用场景截然不同。以下是两者的核心区别及适用场景:

一、核心差异概览

特性 Set Map
存储结构 无序(遍历时保持插入顺序)的唯一值集合 键值对映射(键唯一,值可重复)
元素类型 仅存储值(value) 存储键值对(key-value)
键的特性 无键概念,元素本身即值 键必须唯一,值可重复
键的类型 不适用 键可以是任意类型(包括对象、函数)
重复处理 自动过滤重复值(基于 === 键重复时会覆盖旧值
主要操作 添加(add())、删除(delete())、检查存在性(has() 设置(set())、获取(get())、删除(delete()
遍历方式 values() 或直接用 for...of entries()keys()values()
应用场景 去重、成员检测、维护唯一值集合 缓存、映射关系、需要键值关联的场景

二、具体差异详解

1. 存储结构与元素类型

  • Set
    仅存储值,且每个值必须唯一。

    const set = new Set([1, 2, 2, 3]);
    console.log([...set]); // [1, 2, 3](自动去重)
    
    AI 代码解读
  • Map
    存储键值对,键的唯一性由引用或值决定。

    const map = new Map();
    map.set("name", "John");
    map.set(1, "one"); // 键可以是任意类型
    console.log(map.get("name")); // "John"
    
    AI 代码解读

2. 键的类型与唯一性

  • Set
    无键概念,元素本身即值,重复值会被自动过滤。

    const set = new Set();
    set.add({
         });
    set.add({
         }); // 两个空对象引用不同,均被添加
    console.log(set.size); // 2
    
    AI 代码解读
  • Map
    键可以是任意类型(包括对象、函数),重复键会覆盖旧值。

    const map = new Map();
    const key1 = {
         };
    const key2 = {
         };
    map.set(key1, "value1");
    map.set(key2, "value2"); // 两个空对象引用不同,视为不同键
    console.log(map.size); // 2
    
    // 重复键覆盖示例
    map.set("name", "Alice");
    map.set("name", "Bob"); // 覆盖前一个值
    console.log(map.get("name")); // "Bob"
    
    AI 代码解读

3. 常用方法对比

操作 Set 方法 Map 方法
添加元素 set.add(value) map.set(key, value)
删除元素 set.delete(value) map.delete(key)
检查存在性 set.has(value) map.has(key)
获取元素数量 set.size map.size
清空集合 set.clear() map.clear()
遍历元素 set.forEach(value => {}) map.forEach((value, key) => {})
获取所有值 set.values() 或直接 for...of map.values()
获取所有键 不适用 map.keys()
获取所有键值对 不适用 map.entries() 或直接 for...of

三、应用场景对比

场景 推荐使用 Set 推荐使用 Map
数组去重 [...new Set(arr)] ❌ 不适用
快速检查元素存在性 set.has(value)(O(1)) map.has(key) 需维护键值对
存储对象并按引用查找 set.has(obj) map.get(obj)
统计频率 ❌ 无法直接关联计数 map.set(key, count + 1)
缓存计算结果 ❌ 无键值映射 map.set(input, result)
维护有序的唯一值集合 ✅ 遍历时保持插入顺序 ❌ 键值对结构更适合映射关系

四、性能差异

  • Set

    • 添加、删除、检查存在性的时间复杂度均为 O(1),适合频繁操作。
    • 遍历时按插入顺序返回元素。
  • Map

    • 键值对操作(setgetdelete)的时间复杂度也为 O(1)
    • 遍历时按键的插入顺序返回键值对。

五、示例对比

1. 数组去重

// 使用 Set
const arr = [1, 2, 2, 3];
const unique = [...new Set(arr)];
console.log(unique); // [1, 2, 3]
AI 代码解读

2. 统计字符出现次数

// 使用 Map
const str = "hello";
const charCount = new Map();

for (const char of str) {
   
  charCount.set(char, (charCount.get(char) || 0) + 1);
}

console.log(charCount); // Map(4) { 'h' => 1, 'e' => 1, 'l' => 2, 'o' => 1 }
AI 代码解读

3. 缓存计算结果

// 使用 Map 缓存斐波那契数列结果
const cache = new Map();

function fib(n) {
   
  if (n <= 1) return n;
  if (cache.has(n)) return cache.get(n);

  const result = fib(n - 1) + fib(n - 2);
  cache.set(n, result);
  return result;
}

console.log(fib(10)); // 55(仅计算一次,后续直接从缓存获取)
AI 代码解读

六、总结:如何选择?

  • 使用 Set

    • 需要存储唯一值集合。
    • 频繁检查元素是否存在。
    • 无需键值映射,只需维护值的集合。
  • 使用 Map

    • 需要建立键值对映射关系。
    • 键的类型可能是对象或其他引用类型。
    • 需要按插入顺序遍历键值对。

理解两者差异后,可根据具体需求灵活选择数据结构,提升代码效率和可读性。

目录
打赏
520
57
57
0
129
分享
相关文章
Set中的add()方法和数组的push()方法有什么区别?
Set中的add()方法和数组的push()方法有什么区别?
79 1
for...of循环在遍历Set和Map时的注意事项有哪些?
for...of循环在遍历Set和Map时的注意事项有哪些?
69 0
|
2月前
|
unordered_set、unordered_multiset、unordered_map、unordered_multimap的介绍及使用
unordered_set是不按特定顺序存储键值的关联式容器,其允许通过键值快速的索引到对应的元素。在unordered_set中,元素的值同时也是唯一地标识它的key。在内部,unordered_set中的元素没有按照任何特定的顺序排序,为了能在常数范围内找到指定的key,unordered_set将相同哈希值的键值放在相同的桶中。unordered_set容器通过key访问单个元素要比set快,但它通常在遍历元素子集的范围迭代方面效率较低。它的迭代器至少是前向迭代器。前向迭代器的特性。
120 0
用一棵红黑树同时封装出map和set
再完成上面的代码后,我们的底层代码已经完成了,这时候已经是一个底层STL的红黑树了,已经已符合库里面的要求了,这时候我们是需要给他穿上对应的“衣服”,比如穿上set的“衣服”,那么这个穿上set的“衣服”,那么他就符合库里面set的要求了,同样map一样,这时候我们就需要实现set与map了。因此,上层容器map需要向底层红黑树提供一个仿函数,用于获取T当中的键值Key,这样一来,当底层红黑树当中需要比较两个结点的键值时,就可以通过这个仿函数来获取T当中的键值了。我们就可以使用仿函数了。
36 0
set、map、multiset、multimap的介绍及使用以及区别,注意事项
set是按照一定次序存储元素的容器,使用set的迭代器遍历set中的元素,可以得到有序序列。set当中存储元素的value都是唯一的,不可以重复,因此可以使用set进行去重。set默认是升序的,但是其内部默认不是按照大于比较,而是按照小于比较。set中的元素不能被修改,因为set在底层是用二叉搜索树来实现的,若是对二叉搜索树当中某个结点的值进行了修改,那么这棵树将不再是二叉搜索树。
124 0
flat、flatmap与map的用法区别
本文介绍了 JavaScript 数组方法 `flat()`、`flatMap()` 和 `map()` 的用法及区别。`flat()` 可按指定深度递归展平数组,参数为深度,默认一层;`flatMap()` 结合了 `map()` 和 `flat()` 功能,返回一维数组,长度可能不同于原数组;而 `map()` 返回与原数组长度一致的新数组。通过多个代码示例展示了三者的功能和差异,帮助开发者更好地理解和使用这些方法。
448 0
【c++丨STL】基于红黑树模拟实现set和map(附源码)
本文基于红黑树的实现,模拟了STL中的`set`和`map`容器。通过封装同一棵红黑树并进行适配修改,实现了两种容器的功能。主要步骤包括:1) 修改红黑树节点结构以支持不同数据类型;2) 使用仿函数适配键值比较逻辑;3) 实现双向迭代器支持遍历操作;4) 封装`insert`、`find`等接口,并为`map`实现`operator[]`。最终,通过测试代码验证了功能的正确性。此实现减少了代码冗余,展示了模板与仿函数的强大灵活性。
137 2
哈希表模拟封装unordered_map和unordered_set
哈希表模拟封装unordered_map和unordered_set
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问