高性能内存去重应优先用Map+唯一键实现O(1)判断,整数范围明确时用位图省内存,无唯一键慎用JSON.stringify,超大数据需分块+让出主线程。

高性能的内存缓存去重,核心是“用空间换时间”+“避免重复计算”,关键不在“怎么写”,而在“用什么结构存、按什么逻辑查、在什么前提下缓存”。对百万级数据或高频调用场景,直接用 Array.from(new Set(arr)) 很容易卡死或爆内存。
优先用 Map + 唯一键做 O(1) 缓存判断
90% 的业务对象都有自然唯一标识(如 id、sku、userId),这是最省内存、最快的方式:
- 用
Map存已出现的键值(map.set(key, item)),filter或for循环中查map.has(key),时间复杂度稳定O(n),空间只占去重后数量 - 比
Object更安全:不污染原型链,不会把toString()后的"1"和数字1当成同一个键 - 键缺失时可组合生成,例如
[item.a, item.b].join('|'),但要注意字段顺序和空值处理
整数范围明确时用位图(Bitmap)省 8 倍以上内存
如果数据是密集非负整数(比如状态码 0–255、设备类型 ID 1–65535),位图比 Set 或 Map 节省内存得多:
- 用
Uint8Array或Uint32Array模拟位数组,查n是否存在 → 查第Math.floor(n / 8)字节的第n % 8位 - 浏览器中直接
new Uint8Array(size);Node.js 可用Buffer.alloc()分配紧凑内存 - 不适用于稀疏大范围(如 0–2³²),此时建议分段或引入
RoaringBitmap类库
无唯一键又不能改结构?慎用 JSON.stringify 做临时哈希
仅当对象结构固定、属性顺序一致(如后端返回的标准日志、表单快照)时才考虑:
- 必须确保
{a:1,b:2}和{b:2,a:1}不会同时出现,否则序列化结果不同,导致去重失效 - 性能开销大:每个对象都要转字符串,100 万条可能吃掉 1GB+ 内存
- 只推荐 ≤10 万条、单对象 ≤1KB 的场景;超量请退回自定义键或改用流式分块
超大数据必须分块 + 主线程让出
一次性加载 300 万对象进内存,即使算法再优也容易触发 V8 堆限制(默认约 1.4GB):
- 用
for循环代替filter/map,减少中间数组创建 - 每处理 5 万–10 万条后,Node.js 用
setImmediate,浏览器用setTimeout(fn, 0)让出主线程 - 服务端可结合数据库去重(如 PostgreSQL 的
DISTINCT ON或临时表),把压力从 JS 层卸载出去



















