在JavaScript中,Set和Map的性能有什么区别?

简介: 在JavaScript中,Set和Map的性能有什么区别?

在 JavaScript 中,SetMap 的底层实现均基于哈希表(Hash Table),因此在大多数操作上性能表现相近,但由于设计目的不同,仍存在细微差异。以下是两者性能的详细对比及适用场景分析:

一、核心操作的时间复杂度

操作 Set Map 说明
添加元素 add(value) set(key, value) 均为 O(1) 平均时间复杂度
删除元素 delete(value) delete(key) 均为 O(1) 平均时间复杂度
检查存在性 has(value) has(key) 均为 O(1) 平均时间复杂度
获取元素数量 size size 均为 O(1) 直接返回属性值
遍历所有元素 values() entries() 均为 O(n) 需遍历所有元素
清空集合 clear() clear() 均为 O(1) 重置内部状态

二、性能差异的具体场景

1. 添加与查找操作

  • Set:适用于存储单一值的集合,添加和查找时无需处理键值对映射,略快于 Map。

    const set = new Set();
    set.add(1); // 直接存储值,无需键
    console.log(set.has(1)); // O(1),查找速度快
    
  • Map:需维护键值对映射,操作略复杂,但仍保持 O(1) 时间复杂度。

    const map = new Map();
    map.set("key", 1); // 需处理键值对
    console.log(map.get("key")); // O(1),但多一步键的哈希计算
    

2. 键的类型对性能的影响

  • Set:仅存储值,无需计算键的哈希值,性能稍优。
  • Map:键可以是任意类型(包括对象),需为每个键计算哈希值,开销略高。
    const objKey = {
         };
    map.set(objKey, "value"); // 对象键需额外计算哈希值
    

3. 大数据量下的内存占用

  • Set:仅存储值,内存占用相对较小。
  • Map:需存储键值对,内存占用约为 Set 的两倍(相同数量的元素)。

三、性能测试示例

以下代码对比了 Set 和 Map 在大数据量下的插入和查找性能:

// 测试环境:Chrome 浏览器,100万条数据
const size = 1000000;

// 测试 Set
const set = new Set();
console.time("Set add");
for (let i = 0; i < size; i++) {
   
  set.add(i);
}
console.timeEnd("Set add"); // 约 20-30ms

console.time("Set has");
for (let i = 0; i < size; i++) {
   
  set.has(i);
}
console.timeEnd("Set has"); // 约 15-25ms

// 测试 Map
const map = new Map();
console.time("Map set");
for (let i = 0; i < size; i++) {
   
  map.set(i, i);
}
console.timeEnd("Map set"); // 约 30-40ms

console.time("Map get");
for (let i = 0; i < size; i++) {
   
  map.get(i);
}
console.timeEnd("Map get"); // 约 25-35ms

结果说明

  • 插入操作:Map 比 Set 慢约 30%,因需处理键值对。
  • 查找操作:Map 比 Set 慢约 20%,因需额外处理键的哈希值。

四、性能优化建议

  1. 优先使用 Set 存储单一值集合
    若只需存储唯一值且无需键值映射,Set 的性能和内存效率均优于 Map。

  2. 仅在需要键值映射时使用 Map
    Map 的优势在于支持任意类型的键,且遍历时保持插入顺序,适合缓存、映射关系等场景。

  3. 避免频繁删除和重新添加元素
    哈希表在删除元素后可能不会立即释放内存,频繁删除添加可能导致内存碎片。

  4. 大数据量下的遍历优化
    若需频繁遍历集合,Set 和 Map 的性能相近,但需注意 Map 返回的是键值对,处理开销略高。

五、总结:如何根据性能选择?

场景 推荐使用 Set 推荐使用 Map
存储唯一值集合 ✅ 性能和内存效率更高 ❌ 内存占用多,操作略慢
快速检查元素存在性 ✅ 略快于 Map ❌ 键值对处理开销略高
需要键值映射关系 ❌ 不支持键值对 ✅ 设计初衷即为此场景
键的类型为对象或函数 ❌ 无法通过对象查找 ✅ 支持任意类型的键
大数据量下的频繁插入/删除 ✅ 略优 ❌ 略慢(但仍为 O(1))

理解两者性能差异后,可根据具体业务需求选择合适的数据结构,在保证功能正确性的同时优化性能。

目录
相关文章
|
1月前
|
存储 JavaScript Java
(Python基础)新时代语言!一起学习Python吧!(四):dict字典和set类型;切片类型、列表生成式;map和reduce迭代器;filter过滤函数、sorted排序函数;lambda函数
dict字典 Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。 我们可以通过声明JS对象一样的方式声明dict
158 1
|
4月前
|
存储 缓存 JavaScript
Set和Map有什么区别?
Set和Map有什么区别?
392 1
|
5月前
|
存储 JavaScript 前端开发
Set中的add()方法和数组的push()方法有什么区别?
Set中的add()方法和数组的push()方法有什么区别?
376 122
|
5月前
|
存储 JavaScript 前端开发
for...of循环在遍历Set和Map时的注意事项有哪些?
for...of循环在遍历Set和Map时的注意事项有哪些?
314 121
|
5月前
|
存储 编译器 容器
set、map、multiset、multimap的介绍及使用以及区别,注意事项
set是按照一定次序存储元素的容器,使用set的迭代器遍历set中的元素,可以得到有序序列。set当中存储元素的value都是唯一的,不可以重复,因此可以使用set进行去重。set默认是升序的,但是其内部默认不是按照大于比较,而是按照小于比较。set中的元素不能被修改,因为set在底层是用二叉搜索树来实现的,若是对二叉搜索树当中某个结点的值进行了修改,那么这棵树将不再是二叉搜索树。
245 0
|
Web App开发 JavaScript 前端开发
|
Web App开发 前端开发 JavaScript
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
284 2
|
JavaScript 前端开发
JavaScript中的原型 保姆级文章一文搞懂
本文详细解析了JavaScript中的原型概念,从构造函数、原型对象、`__proto__`属性、`constructor`属性到原型链,层层递进地解释了JavaScript如何通过原型实现继承机制。适合初学者深入理解JS面向对象编程的核心原理。
215 1
JavaScript中的原型 保姆级文章一文搞懂
|
12月前
JS+CSS3文章内容背景黑白切换源码
JS+CSS3文章内容背景黑白切换源码是一款基于JS+CSS3制作的简单网页文章文字内容背景颜色黑白切换效果。
140 0
下一篇
oss云网关配置