🌱BeginnerData Structures

Sets and Maps

ES6 Set and Map unique value collections and key-value stores with any key type.

Overview

ES6 introduced `Set` and `Map` as first-class collection types to complement arrays and plain objects. **Set** is a collection of unique values duplicates are automatically ignored. It's perfect for deduplication, membership checks, and set operations (union, intersection, difference). Unlike arrays, Sets have O(1) `.has()` lookups. **Map** is a key-value store like a plain object, but with crucial advantages: keys can be any value (not just strings), insertion order is preserved, and Maps have cleaner size/iteration APIs. Use a Map when you need non-string keys, need to count occurrences, or need a clean key-value API without the prototype clutter of plain objects. Both are iterable with `for...of` loops and support the spread operator: `[...mySet]`, `[...myMap]`.

Key Points

  • •`new Set([iterable])` unique values; `.add(v)`, `.has(v)`, `.delete(v)`, `.size`, `.clear()`
  • •`[...new Set(array)]` the fastest way to remove duplicates from an array
  • •`new Map([[key, val], ...])` key-value store; `.set(k, v)`, `.get(k)`, `.has(k)`, `.delete(k)`, `.size`
  • •Map keys can be objects, functions, numbers any value; plain object keys are always strings
  • •Both preserve insertion order and are iterable with `for...of`
  • •`map.entries()` iterator of `[key, value]` pairs; `map.keys()`, `map.values()`
  • •WeakSet and WeakMap hold weak references good for caching without preventing garbage collection

Examples

Set unique values and membership

// Create a Set
const fruits = new Set(["apple", "banana", "apple", "cherry"]);
console.log(fruits);       // Set(3) {"apple", "banana", "cherry"}
console.log(fruits.size);  // 3

// Add and check
fruits.add("mango");
fruits.add("apple");      // duplicate ignored
console.log(fruits.has("banana"));   // true
console.log(fruits.has("grape"));    // false

// Remove duplicates from an array
const nums = [1, 2, 2, 3, 3, 3, 4];
const unique = [...new Set(nums)];
console.log(unique);  // [1, 2, 3, 4]

// Set operations
const a = new Set([1, 2, 3, 4]);
const b = new Set([3, 4, 5, 6]);
const union        = new Set([...a, ...b]);        // {1,2,3,4,5,6}
const intersection = new Set([...a].filter(x => b.has(x)));  // {3,4}
const difference   = new Set([...a].filter(x => !b.has(x))); // {1,2}
console.log([...union], [...intersection], [...difference]);

Map flexible key-value store

// Create a Map
const scores = new Map();
scores.set("Alice", 95);
scores.set("Bob",   87);
scores.set("Carol", 92);

console.log(scores.get("Alice"));   // 95
console.log(scores.has("Dave"));    // false
console.log(scores.size);           // 3

// Non-string keys
const userMap = new Map();
const userObj = { id: 1 };
userMap.set(userObj, { role: "admin" });
console.log(userMap.get(userObj));  // {role: "admin"}

// Iterate
for (const [name, score] of scores) {
  console.log(`${name}: ${score}`);
}

// Convert Map to object
const obj = Object.fromEntries(scores);
console.log(obj);  // {Alice: 95, Bob: 87, Carol: 92}

Map for counting occurrences

function countWords(text) {
  const counts = new Map();
  for (const word of text.toLowerCase().split(/\s+/)) {
    counts.set(word, (counts.get(word) ?? 0) + 1);
  }
  return counts;
}

const wc = countWords("the quick brown fox jumps over the lazy fox");
console.log(wc.get("the"));   // 2
console.log(wc.get("fox"));   // 2

// Sort by count convert to array first
const sorted = [...wc.entries()].sort((a, b) => b[1] - a[1]);
sorted.slice(0, 3).forEach(([w, c]) => console.log(`${w}: ${c}`));

Common Mistakes

  • Using `.length` on a Set or Map they use `.size`, not `.length`
  • Accessing Map values with bracket notation (`map["key"]`) this sets a plain property, not a Map entry; always use `.get()` and `.set()`
  • Expecting that two object literals with the same content are the same key in a Map `map.set({a:1}, x)` and `map.get({a:1})` returns `undefined` because they're different object references

Note

Rule of thumb: use a Set when you care about uniqueness; use a Map when you need non-string keys or want cleaner semantics than a plain object. For most string-key lookups where you own the keys, a plain object `{}` is simpler and faster.

Exercises

Write JavaScript code to solve each exercise. Run it and check your output.

Loading editor…

Completed: 0 / 5 exercises

Knowledge Check

Question 1 of 4

What happens when you add a duplicate value to a Set?