数据结构对决:Set vs Map

203 阅读4分钟

前言

下面聊聊set和map的特殊的点吧~

Set为ES6提供的一种新的数据结构,它类似于数组,但是成员的值都必须是唯一的,没有重复的值。

Map解决了传统意义是只能将字符串当作键的问题。

正文

关于Set实例的创建

const s = new Set();

set的系列方法

  • add(value) : 向集合中添加一个新元素。如果该值已经存在,则不会重复添加。
  • delete(value) : 删除集合中的某个值。如果值存在,则返回 true,否则返回 false
  • has(value) : 检查集合中是否包含某个值,返回 true 或 false
  • clear() : 清空集合中的所有元素。
  • size: 属性,返回集合中元素的数量。

set的属性方法

  • Set.keys():返回键名的遍历器
  • Set.values():返回键值的遍历器
  • Set.entries():返回键值对的遍历器
  • Set.forEach():使用回调函数遍历每个成员

代码实操:

const s = new Set();
s.add(1);
s.add(2);

console.log(s);
console.log(s.keys()); // 键名
console.log(s.values()); // 值
console.log(s.entries()); // 键值对

image.png

还可以通过传入数据的方法来初始化一个Set实例:

const s = new Set([1, 2, 3, 3]);

遍历Set对象的方法

const s = new Set([1, 2, 3, 3]);

for (let item of s) { // 专门用来遍历具有iterable(迭代器)属性的结构
    console.log(item);
}

image.png

也可以用来遍历键值:

const s = new Set([1, 2, 3, 3]);

for (let item of s.keys()) { // 专门用来遍历具有iterable(迭代器)属性的结构
    console.log(item);
}

image.png

可以使用 [...new Set(arr)]来对数组去重

const arr = [1, 2, 3, 4, 4, 3, 2, 1];
const arr2 = [...new Set(arr)];

console.log(arr2);

image.png

WeakSet和set有什么区别呢?

WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别:

  • WeakSet 的成员只能是对象Symbol 值,而不能是其他类型的值
  • WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中

第二点可能有点不太容易理解,通过代码实例来进行解释:

let obj = {name: '玛卡巴卡'};
let ws = new WeakSet();

ws.add(obj);
obj = null; // 如果一个对象被人为的置为null,一定会第一时间被回收掉

console.log(ws);

image.png

总结:

  • 弱引用
  1. 一个对象obj存放在了其他的结构中,当后续存在其他对象引用这个对象,那么这个对象的内存就不会被回收
  2. 一个对象obj存在了其他的结构中,当后续只存在WeakSet对它的引用,该对象的内存依然会被回收

Map实例的创建

const m = new Map(); // 可以用任意类型做key

map的系列方法

  • set(key, value) : 添加或设置键值对。如果键已存在,则更新对应的值。
  • get(key) : 根据键获取值,如果键不存在则返回 undefined
  • has(key) : 判断 Map 中是否存在某个键,返回布尔值。
  • delete(key) : 删除指定键及其对应的值,如果删除成功返回 true,否则返回 false
  • clear() : 清空 Map 中的所有键值对。
  • size: 属性,返回 Map 中键值对的数量。

map的属性方法

  • Map.keys():返回键名的遍历器。
  • Map.values():返回键值的遍历器。
  • Map.entries():返回所有成员的遍历器。
  • Map.forEach():遍历 Map 的所有成员。

代码:

const m = new Map(); // 可以用任意类型做key
const o = {age: 18};
m.set(o, [1, 2, 3]);

console.log(m);
console.log(m.keys());
console.log(m.values());
console.log(m.entries());

image.png

代码:

const m = new Map(); // 可以用任意类型做key
const o = {age: 18};
m.set(o, [1, 2, 3]);

m.delete(o);
console.log(m.get(o));
console.log(m.has(o));

image.png

WeakMap和map有什么区别呢?

WeakMap结构与Map结构类似,也是用于生成键值对的集合,但是WeakMapMap的区别有两点:

  • WeakMap只接受对象(null除外)和 Symbol 值作为键名,不接受其他类型的值作为键名。
  • WeakMap的键名所指向的对象,不计入垃圾回收机制。

WeakMap的专用场合就是,它的键所对应的对象,可能会在将来消失。WeakMap 结构有助于防止内存泄漏。

注意,WeakMap 弱引用的只是键名,而不是键值,键值依然是正常引用