Sets and Maps from Four Semesters of Computer Science in 5 Hours by Brian Holt
Posted on August 24, 2020 in Algorithms, JavaScript by Matt Jennings
Set
Set
objects are collections of values. Sets are reference data types, like Arrays, and allow unique lists (ONLY unique values unliked Arrays). Sets are also iterable like Arrays.
Sets can’t be accessed like Arrays (like arr[0] = 0;
) and don’t have indices.
Example:
let myArray = [11, 22, 34, 65, 34]; let mySet = new Set(myArray); console.log(mySet) // Set {11, 22, 34, 65} mySet.add('100'); console.log(mySet); // Set {11, 22, 34, 65, '100'} mySet.delete(22); console.log(mySet); // Set {11, 34, 65, '100'} console.log(mySet.size); // 4 // Loop through a set using forEach mySet.forEach(val => { console.log(val); }); // Loop through a set using for of for(let val of mySet) { console.log(val); } console.log(mySet.has(11)); // true // To create empty Set mySet.clear();
WeakSet
The WeakSet
objects are collections of objects, just like Set
objects. Also, all objects in WeakSet
objects must be unique. However, unlike Set
objects, WeakSet
objects:
- Are collections of objects only. They can’t contain values of any type, like
Set
objects can. - Are weak, meaning that references to objects in a
WeakSet
are held weakly. If no other references to an object stored in aWeakSet
exist, those objects can be garbage collected, which means they’ll be removed from memory.
Finally, WeakSet
objects are not enumerable.
let carWeakMap = new WeakMap(); let car1 = { make: 'Hondo', model: 'Civic' }; carWeakSet.add(car1); console.log(carWeakSet); // WeakSet {Object: {make: "Honda", model: "Civic"}} carWeakSet.delete(car1); // WeakSet {}
Map
The Map
object holds key-value pairs and remembers the original insertion order of the keys. Objects and primitive values may be used as either a key or a value.
Some differences between Object
and Map
objects are:
- The keys of
Map
can be any value, including functions, objects, or primitives. - The keys in
Map
are ordered. Thus, when iterating over it, aMap
object returns keys in order of insertion. - The number of items in a
Map
is easily retrieved from itssize
property. - A
Map
is iterable. - A
Map
can perform better than anObject
in same scenarios involving frequent additions and removals of key-value pairs.
Code examples:
let myMap = new Map() let keyString = 'a string' let keyObj = {} let keyFunc = function() {} // setting the values myMap.set(keyString, "value associated with 'a string'") myMap.set(keyObj, 'value associated with keyObj') myMap.set(keyFunc, 'value associated with keyFunc') myMap.size // 3 // getting the values myMap.get(keyString) // "value associated with 'a string'" myMap.get(keyObj) // "value associated with keyObj" myMap.get(keyFunc) // "value associated with keyFunc" myMap.get('a string') // "value associated with 'a string'" // because keyString === 'a string' myMap.get({}) // undefined, because keyObj !== {} let myMap = new Map() myMap.set(0, 'zero') myMap.set(1, 'one') for (let [key, value] of myMap) { console.log(key + ' = ' + value) } // 0 = zero // 1 = one for (let key of myMap.keys()) { console.log(key) } // 0 // 1 for (let value of myMap.values()) { console.log(value) } // zero // one for (let [key, value] of myMap.entries()) { console.log(key + ' = ' + value) } // 0 = zero // 1 = one myMap.get(function() {}) // undefined, because keyFunc !== function () {} let myMap = new Map() myMap.set(0, 'zero') myMap.set(1, 'one') for (let [key, value] of myMap) { console.log(key + ' = ' + value) } // 0 = zero // 1 = one for (let key of myMap.keys()) { console.log(key) } // 0 // 1 for (let value of myMap.values()) { console.log(value) } // zero // one for (let [key, value] of myMap.entries()) { console.log(key + ' = ' + value) } // 0 = zero // 1 = one myMap.forEach(function(value, key) { console.log(key + ' = ' + value) }) // 0 = zero // 1 = one
WeakMap
The WeakMap
object is a collection of key/value pairs in which the keys are weakly referenced. The keys must be objects and the values can be arbitrary values.
Keys of WeakMaps are of the type Object
only. Primitive data types as keys are not allowed (e.g. a Symbol
can’t be a WeakMap
key).
Native WeakMap
s hold “weak” references to key objects, which means that they do not prevent garbage collection in case there would be no other reference to the key object.
Because the references are weak, WeakMap
keys are not enumerable.
Code examples:
const wm1 = new WeakMap(), wm2 = new WeakMap(), wm3 = new WeakMap(); const o1 = {}, o2 = function() {}, o3 = window; wm1.set(o1, 37); wm1.set(o2, 'azerty'); wm2.set(o1, o2); // a value can be anything, including an object or a function wm2.set(o3, undefined); wm2.set(wm1, wm2); // keys and values can be any objects. Even WeakMaps! wm1.get(o2); // "azerty" wm2.get(o2); // undefined, because there is no key for o2 on wm2 wm2.get(o3); // undefined, because that is the set value wm1.has(o2); // true wm2.has(o2); // false wm2.has(o3); // true (even if the value itself is 'undefined') wm3.set(o1, 37); wm3.get(o1); // 37 wm1.has(o1); // true wm1.delete(o1); wm1.has(o1); // false