核心是避免内存爆掉、主线程卡死及误判边界情况;需分层应对:优先后端去重,前端必须处理时,基础类型用分块set,对象数组用map按字段流式去重,超大文件则结合readablestream与bloom filter。

对大文件或超长数组做安全去重,核心不是“选哪种方法”,而是避免内存爆掉、主线程卡死、或误判 NaN/对象等边界情况。普通 Set 一行解决在小数组上很香,但面对百万级元素或含大量对象的数组,必须分层应对。
先判断是不是真需要前端去重
多数真实场景中,超长数组来自接口响应——优先考虑让后端加去重逻辑或分页时过滤重复。前端强行处理百万项数组,既慢又占内存,还可能触发浏览器内存警告。如果必须前端做,再往下看。
基础类型大数组:用 Set + 分块处理
Set 虽快(O(n)),但一次性把百万项塞进 new Set(arr) 仍会瞬间占用大量内存。更稳妥的做法是分批构建 Set:
- 按每 10 万项为一组,循环调用 new Set(chunk),再合并到一个主 Set 中
- 用 requestIdleCallback 或 setTimeout(..., 0) 切割任务,防止界面卡顿
- 最后用 Array.from(mainSet) 得到结果,不依赖扩展运算符(避免栈溢出)
含对象或复杂结构的数组:按字段 + Map 流式去重
直接对对象数组用 Set 没用——每个 {} 都是不同引用。正确做法是提取唯一标识字段(如 id、name),用 Map 缓存已见过的键:
- 遍历数组时,计算 item.id + '' 或 JSON.stringify(pick(item, ['id', 'type'])) 作为 key
- 用 Map.has(key) 判断是否已存在,没出现过才 push 到结果数组
- 慎用 JSON.stringify:仅限结构稳定、不含函数/undefined/循环引用的对象;否则改用 Lodash 的 _.isEqual 或自定义哈希函数
极端情况:内存受限或需流式处理
比如读取 GB 级本地文件(通过 FileReader + Stream API),根本无法全量加载进内存:
- 用 ReadableStream 分片读取文本行或 JSON 行(NDJSON)
- 每读一块,解析成对象,按字段查 Map 或布隆过滤器(Bloom Filter)快速判重
- 重复项直接丢弃,非重复项写入新 Blob 或暂存 IndexedDB,避免堆内存堆积
不复杂但容易忽略:去重前先确认数据形态。数字和字符串混排?有 null/undefined/NaN?对象字段是否总有值?这些细节决定你该用 Set、Map 还是自定义比较逻辑,而不是硬套某一种“最热解法”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











