真实百万级数据测试比理论更可靠,需避免垃圾回收干扰、确保数据贴近业务、一次只比一种策略;应构造3组不同重复率数组,统一用console.time测时并清空内存,聚焦Set展开、Map标记、双指针三类典型实现。

直接用 console.time + 真实百万级数据测,比看理论更可靠。关键不是“怎么测”,而是“怎么测才不跑偏”——比如避免垃圾回收干扰、确保数据特征贴近业务、一次只比一种策略。
构造有代表性的测试数据
别用 Math.random() 堆满一千万个数就开跑。重复率、数据类型、是否有序,直接影响算法表现:
- 准备 3 组数组:100 万条,分别含 20% / 50% / 80% 重复率(比如用
Array.from({length: 800000}, (_, i) => i % 1000)控制重复密度) - 基础类型用数字或字符串;对象数组则统一带
id字段,如{ id: 1, name: 'a' } - 有序数组单独准备一份(如
[1,1,2,2,3,3,...]),用来验证双指针方案
统一测试框架,排除干扰
每次只运行一个去重函数,前后加时间标记,并清空内存影响:
- 用
console.time('set')和console.timeEnd('set')包裹调用 - 每次测试前加
gc?.()(Node.js 开启--expose-gc后可用;浏览器中不强制,但可手动触发几次小数组回收) - 避免在同一个作用域反复调用多个方法——函数间变量/闭包可能互相污染,建议每个方法单独执行
- 重复跑 3–5 次,取中间值,跳过首轮(V8 预热)和明显异常的峰值
重点对比这几类典型实现
不用全写 7 种,聚焦真正有区分度的:
-
Set 展开法:
[...new Set(arr)]—— 基础类型标尺,通常 10–20ms -
Map 标记法(对象数组):
arr.filter(item => !map.has(item.id) && map.set(item.id, 1))—— 有唯一键时的首选,约 15–25ms -
双指针(仅限有序):
let slow = 0; for (let fast = 1; fast —— 原地、O(1) 空间,快且稳 - filter + indexOf —— 对照组,百万数据大概率超 800ms,卡顿明显,用来反向验证优化价值
注意结果里的隐藏信号
耗时数字背后还有信息:
- 如果 Set 方法突然变慢(比如 >50ms),可能是数组里混了大量对象或嵌套结构,触发隐式转换或哈希冲突
- Map 方法比 Set 还慢?检查是否误用了
map.get(item.id) === undefined而非map.has(),后者才是 O(1) - 双指针在无序数组上跑出错误结果?说明没先排序——它本身不负责排序,不能直接套用
- 所有方法内存暴涨?考虑分块处理,比如每 5 万条一批,用
setTimeout(0)让出主线程


















