百万级数组去重首选set+展开语法,时间复杂度o(n),支持nan相等判断;对象数组按字段去重用map;有序数组可用快慢双指针原地去重。

处理百万级数组去重,核心就一条:别用 indexOf、includes 或双层循环——它们会触发 O(n²) 时间复杂度,50 万数据就可能卡住几秒甚至分钟。
首选 Set + 展开语法(基础类型最快)
对数字、字符串、布尔值、null、undefined、NaN 等基本类型,这是目前最高效、最简洁的方案:
- 时间复杂度 O(n),空间换时间,现代 JS 引擎对 Set 优化极好
- 代码只需一行:
[...new Set(arr)]或Array.from(new Set(arr)) - 能正确识别
NaN === NaN(其他方法常在这里翻车) - 注意:不处理对象或数组等引用类型——两个
{}仍会被视为不同元素
对象数组按字段去重(如 id、name)
当数组元素是对象,且你有唯一标识字段(比如 id),用 Map 记录已见 key,避免重复创建对象:
- 比用普通对象更安全(不会把
1和"1"当成同一个键) - 示例:
arr.filter(item => !map.has(item.id) && map.set(item.id, true)) - 初始化
const map = new Map(),整个过程仍是 O(n) - 若字段嵌套较深(如
item.user.profile.id),可先用map提取键,再统一去重
原地去重(内存极度敏感场景)
如果数组已排序,且必须复用原数组空间(如嵌入式环境或超大 buffer),用快慢双指针:
- 只遍历一次,不新建数组,空间复杂度 O(1)
- 适用于
[1,1,2,2,3]类有序输入,返回新长度,前 n 项即结果 - 代码骨架:
let slow = 1; for (let fast = 1; fast - 无序数组不能直接用——得先
sort(),但排序本身是 O(n log n),还可能改变原始顺序
慎用或避免的方法
以下方法在百万量级下明显拖慢速度或行为不可靠:
-
filter + indexOf:每次indexOf都从头扫,O(n²),实测 10 万数据就超 1 秒 -
reduce + includes:同理,includes是线性查找 -
JSON.stringify判重:序列化开销大,且对函数、undefined、Symbol、循环引用直接报错或失效 - 双重
for循环 +splice:不仅慢,频繁修改数组长度还会导致索引错乱和性能抖动
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











