set 通过哈希表实现 o(1) 平均查找,比数组的 o(n) includes 快百倍;应一次性初始化 set 后复用,适用于存在性检查,但不支持索引、排序或深比较。

用 Set 替代数组或对象做存在性检查,能将时间复杂度从 O(n) 降到 O(1) 平均情况,特别适合高频、大批量的 includes 或 indexOf 场景。
为什么 Set 比数组快得多
数组的 includes()、indexOf() 都要逐项遍历比对,数据量越大越慢;而 Set 内部基于哈希表(或类似机制)实现,查找时直接计算键的存储位置,无需遍历。
- 10 万个元素的数组:
arr.includes(x)平均查 5 万次比较 - 同样 10 万个元素的 Set:
set.has(x)通常只需 1–2 次操作 - 实测中,百万级数据下
has()比includes()快 100 倍以上
怎么把现有数据转成 Set 并正确使用
初始化一次,复用多次 —— 这是性能提升的关键。避免在循环里反复创建 Set。
- 从数组创建:
const idSet = new Set(idArray); - 从对象 keys 创建:
const keySet = new Set(Object.keys(obj)); - 检查是否存在:
if (idSet.has(targetId)) { ... }(别再写idArray.includes(targetId)) - 注意:Set 只支持精确相等(
===),对对象引用敏感;如需深比较,仍需额外处理
实际优化案例:过滤重复请求或去重校验
比如前端批量提交用户 ID,需跳过已处理过的:
- ❌ 低效写法(每次遍历数组):
if (!processedIds.includes(id)) { process(id); processedIds.push(id); } - ✅ 高效写法(用 Set 缓存 +
has):const processedSet = new Set();<br>ids.forEach(id => {<br> if (!processedSet.has(id)) {<br> process(id);<br> processedSet.add(id);<br> }<br>});
小提醒:Set 的局限和替代选择
Set 不是万能的。要注意这些边界情况:
- 只存原始值或引用,不能直接存带结构的数据(如想按 name 查 user,得配合 Map)
- 不支持下标访问或排序,仅用于“有无”判断
- 内存略高于纯数组(有哈希表开销),但对百万级以下数据影响极小
- 如果需要同时存值 + 元数据(比如“ID 是否已审核”),优先考虑
Map:const statusMap = new Map([[id, 'approved']]);
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











