Skip to main content
โšก Calmops

Map and Set Collections

Map and Set Collections

Map and Set are built-in collections that provide alternatives to objects and arrays for specific use cases.

Set Collection

A Set stores unique values of any type:

const set = new Set();

set.add(1);
set.add(2);
set.add(3);
set.add(2); // Duplicate - ignored

console.log(set.size); // 3
console.log(set); // Set(3) { 1, 2, 3 }

Creating Sets

// Empty set
const empty = new Set();

// From array
const fromArray = new Set([1, 2, 3, 2, 1]);
console.log(fromArray); // Set(3) { 1, 2, 3 }

// From string
const fromString = new Set("hello");
console.log(fromString); // Set(4) { 'h', 'e', 'l', 'o' }

Set Methods

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

// add() - add element
set.add(4);
console.log(set); // Set(4) { 1, 2, 3, 4 }

// has() - check if element exists
console.log(set.has(2)); // true
console.log(set.has(5)); // false

// delete() - remove element
set.delete(2);
console.log(set); // Set(3) { 1, 3, 4 }

// clear() - remove all elements
set.clear();
console.log(set); // Set(0) {}

Iterating Sets

const set = new Set(["apple", "banana", "orange"]);

// for...of loop
for (const item of set) {
    console.log(item);
}

// forEach method
set.forEach(item => {
    console.log(item);
});

// Destructuring
const [first, second] = set;
console.log(first, second); // "apple", "banana"

Practical Set Examples

Remove Duplicates

const numbers = [1, 2, 2, 3, 3, 3, 4];
const unique = [...new Set(numbers)];
console.log(unique); // [1, 2, 3, 4]

Check for Unique Values

function hasUniqueValues(arr) {
    return arr.length === new Set(arr).size;
}

console.log(hasUniqueValues([1, 2, 3])); // true
console.log(hasUniqueValues([1, 2, 2])); // false

Find Common Elements

function findCommon(arr1, arr2) {
    const set1 = new Set(arr1);
    return arr2.filter(item => set1.has(item));
}

console.log(findCommon([1, 2, 3], [2, 3, 4])); // [2, 3]

Map Collection

A Map stores key-value pairs where keys can be any type:

const map = new Map();

map.set("name", "Alice");
map.set("age", 30);
map.set(1, "one");

console.log(map.size); // 3
console.log(map.get("name")); // "Alice"

Creating Maps

// Empty map
const empty = new Map();

// From array of pairs
const fromArray = new Map([
    ["name", "Alice"],
    ["age", 30],
    ["city", "New York"]
]);

console.log(fromArray.get("name")); // "Alice"

Map Methods

const map = new Map();

// set() - add or update
map.set("key1", "value1");
map.set("key2", "value2");

// get() - retrieve value
console.log(map.get("key1")); // "value1"

// has() - check if key exists
console.log(map.has("key1")); // true
console.log(map.has("key3")); // false

// delete() - remove entry
map.delete("key1");
console.log(map.has("key1")); // false

// clear() - remove all entries
map.clear();
console.log(map.size); // 0

Map Keys

Map keys can be any type:

const map = new Map();

// String key
map.set("string", "value1");

// Number key
map.set(1, "value2");

// Object key
const obj = { id: 1 };
map.set(obj, "value3");

// Function key
const fn = () => {};
map.set(fn, "value4");

console.log(map.size); // 4
console.log(map.get(obj)); // "value3"

Iterating Maps

const map = new Map([
    ["name", "Alice"],
    ["age", 30],
    ["city", "New York"]
]);

// for...of loop
for (const [key, value] of map) {
    console.log(`${key}: ${value}`);
}

// forEach method
map.forEach((value, key) => {
    console.log(`${key}: ${value}`);
});

// Get keys
console.log([...map.keys()]); // ["name", "age", "city"]

// Get values
console.log([...map.values()]); // ["Alice", 30, "New York"]

// Get entries
console.log([...map.entries()]); // [["name", "Alice"], ...]

Practical Map Examples

Cache with Expiration

class Cache {
    constructor() {
        this.cache = new Map();
    }
    
    set(key, value, ttl = 60000) {
        this.cache.set(key, { value, expiry: Date.now() + ttl });
    }
    
    get(key) {
        const item = this.cache.get(key);
        if (!item) return null;
        
        if (Date.now() > item.expiry) {
            this.cache.delete(key);
            return null;
        }
        
        return item.value;
    }
}

const cache = new Cache();
cache.set("user", { id: 1, name: "Alice" });
console.log(cache.get("user")); // { id: 1, name: "Alice" }

Group by Property

function groupBy(arr, key) {
    const map = new Map();
    
    arr.forEach(item => {
        const groupKey = item[key];
        if (!map.has(groupKey)) {
            map.set(groupKey, []);
        }
        map.get(groupKey).push(item);
    });
    
    return map;
}

const users = [
    { name: "Alice", role: "admin" },
    { name: "Bob", role: "user" },
    { name: "Charlie", role: "admin" }
];

const grouped = groupBy(users, "role");
console.log(grouped.get("admin")); // [Alice, Charlie]
console.log(grouped.get("user")); // [Bob]

Frequency Counter

function countFrequency(arr) {
    const map = new Map();
    
    arr.forEach(item => {
        map.set(item, (map.get(item) || 0) + 1);
    });
    
    return map;
}

const items = ["a", "b", "a", "c", "b", "a"];
const frequency = countFrequency(items);

console.log(frequency.get("a")); // 3
console.log(frequency.get("b")); // 2
console.log(frequency.get("c")); // 1

Map vs Object

Feature Map Object
Key types Any type String or Symbol
Size .size property Manual counting
Iteration Built-in methods for…in loop
Performance Better for frequent add/delete Better for static data
Serialization Not JSON serializable JSON serializable
// Map - any key type
const map = new Map();
map.set(1, "one");
map.set("1", "string one");
map.set(true, "boolean");

// Object - keys converted to strings
const obj = {};
obj[1] = "one";
obj["1"] = "string one"; // Overwrites previous
obj[true] = "boolean"; // Overwrites previous

Set vs Array

Feature Set Array
Duplicates Not allowed Allowed
Order Insertion order Index-based
Performance O(1) lookup O(n) lookup
Methods add, delete, has push, pop, splice
// Set - unique values
const set = new Set([1, 2, 2, 3]);
console.log(set.size); // 3

// Array - allows duplicates
const arr = [1, 2, 2, 3];
console.log(arr.length); // 4

WeakMap and WeakSet

WeakMap and WeakSet hold weak references (objects can be garbage collected):

// WeakMap - keys must be objects
const weakMap = new WeakMap();
const obj = { id: 1 };
weakMap.set(obj, "value");

// WeakSet - values must be objects
const weakSet = new WeakSet();
weakSet.add(obj);

// No .size property
// No iteration methods
// Used for private data

Practical WeakMap Example

const privateData = new WeakMap();

class User {
    constructor(name) {
        this.name = name;
        privateData.set(this, { password: "secret" });
    }
    
    getPrivateData() {
        return privateData.get(this);
    }
}

const user = new User("Alice");
console.log(user.getPrivateData()); // { password: "secret" }

Summary

  • Set: stores unique values of any type
  • Map: stores key-value pairs with any key type
  • Set methods: add(), has(), delete(), clear()
  • Map methods: set(), get(), has(), delete(), clear()
  • Iteration: for…of, forEach(), keys(), values(), entries()
  • WeakMap/WeakSet: weak references for garbage collection
  • Use Set: for unique values, membership testing
  • Use Map: for key-value associations, better than objects

Official Documentation

Next Steps

  1. Callbacks and Asynchronous JavaScript
  2. Promises: Creation, Chaining, Resolution
  3. Async/Await: Modern Asynchronous Programming

Comments