set按内存地址而非内容去重,因使用samevaluezero算法,对象间===只比较引用;按内容去重需json.stringify排序键、提取id、map自定义key或第三方深比较库。

JavaScript 中 Set 对引用类型(如对象、数组)去重时,**不会按内容比较,而是按内存地址判断是否相等**。所以即使两个对象字面量一模一样({a: 1, b: 2}),只要不是同一个引用,Set 就会把它们视为不同元素,无法去重。
为什么两个“相同”的对象在 Set 中不被去重?
Set 内部使用 SameValueZero 算法判断重复,对对象来说等价于 ===(严格相等)。而对象的 === 比较只看是否指向同一块内存,和属性、结构、值完全无关。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
例如:
const set = new Set();
set.add({a: 1});
set.add({a: 1});
console.log(set.size); // 2 —— 两个不同对象,都加进去了
想按内容去重,常见解决思路
-
转为唯一字符串键:用
JSON.stringify()序列化对象(注意:仅适用于可序列化的简单对象,且属性顺序敏感、不支持函数/undefined/Symbol/循环引用) -
手动定义唯一标识符:如果对象有业务上稳定的主键(如
id字段),直接用该字段构建 Set:new Set(arr.map(item => item.id)) - 用 Map + 自定义 key 生成逻辑:写一个函数提取或生成能代表对象“内容特征”的字符串(比如深比较后哈希,或拼接关键字段),再用这个字符串作 Map 的 key 来实现逻辑去重
-
借助第三方库:如
lodash.isEqual配合Array.filter()+findIndex手动去重;或用fast-deep-equal做高效深比较
一个轻量实用的按内容去重函数示例
适用于扁平对象(无嵌套、无函数):
function uniqueByContent(arr) {
const seen = new Set();
return arr.filter(obj => {
const key = JSON.stringify(Object.keys(obj).sort().map(k => [k, obj[k]]));
if (seen.has(key)) return false;
seen.add(key);
return true;
});
}
uniqueByContent([{a:1,b:2}, {b:2,a:1}, {a:1}]);
// → [{a:1,b:2}, {a:1}](注意:JSON.stringify({a:1,b:2}) !== JSON.stringify({b:2,a:1}),所以需先排序键)
总结关键点
-
Set天然只认引用,不认内容 - 没有银弹方案,要根据对象结构、性能要求、是否可序列化来选策略
- 若需频繁按内容查重,建议从数据设计阶段就引入稳定 ID 或归一化结构
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










