map比普通对象更适合频次统计,因其保持插入顺序、键类型不限(支持对象/函数/nan)、get/set时间复杂度稳定o(1);而普通对象键强制转字符串,对引用类型不安全且丢失类型信息。

用 Map 记录频次来实现数组去重,本质上是“边统计边过滤”,比先 new Set() 再转回数组或嵌套循环更可控,尤其适合需要保留首次出现顺序、同时兼顾性能与可扩展性的场景。
为什么 Map 比普通对象更适合频次统计
Map 保持插入顺序,键类型不限(支持对象、函数、NaN 等),且 get/set 时间复杂度稳定为 O(1);而普通对象的键会被强制转为字符串,{[1,2]: 1} 实际变成 {"1,2": 1},对引用类型不安全,也丢失原始类型信息。
基础写法:用 Map 去重并保留首次出现顺序
核心思路:遍历数组,用 Map 记录某值是否已出现过(值设为 true 或频次数字),未出现则推入结果数组。
示例代码:
function uniqueByMap(arr) {
const seen = new Map();
const result = [];
for (const item of arr) {
if (!seen.has(item)) {
seen.set(item, true);
result.push(item);
}
}
return result;
}
// 使用
uniqueByMap([1, 2, 2, 3, 1, 'a', 'a']); // [1, 2, 3, 'a']
进阶用法:带频次统计的去重(如只保留出现 ≥2 次的元素)
若目标不是“去重”,而是“筛选高频元素”,可在遍历中累加频次,第二遍再过滤:
- 第一遍:用
Map统计每个值出现次数 - 第二遍:按条件筛选(如
count >= 2),同时用另一个Map或Set避免重复添加同一元素多次
function filterByFrequency(arr, minFreq = 2) {
const freq = new Map();
for (const item of arr) {
freq.set(item, (freq.get(item) || 0) + 1);
}
const seen = new Map();
const result = [];
for (const item of arr) {
const count = freq.get(item);
if (count >= minFreq && !seen.has(item)) {
seen.set(item, true);
result.push(item);
}
}
return result;
}
filterByFrequency([1, 2, 2, 3, 3, 3, 4], 2); // [2, 3]
注意事项与性能提醒
-
原始类型直接作 key 安全:数字、字符串、布尔、symbol、undefined 可直接用作
Map键 -
对象/数组需序列化或用 WeakMap:若数组含对象,
map.has(obj)判断的是引用相等;想按内容去重,得先JSON.stringify(注意循环引用和属性顺序)或用第三方库如fast-deep-equal - 小数组不必过度优化:长度 [...new Set(arr)] 更简洁;Map 优势在大数组(10⁴+)、需频次逻辑、或混合类型场景
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











