Introduction
Imagine checking whether a word has appeared before by reading through a list every time. With a thousand words that works. With a million it is painfully slow. Maps and Sets are built to answer lookup questions directly, without looking at every item, and this is often the difference between a program that works and one that freezes.
How it works
Map stores pairs. You give it a key and it finds the value.
| Code | Effect |
|---|---|
new Map() | an empty map |
m.set(key, value) | adds or replaces a pair |
m.get(key) | the value, or undefined |
m.has(key) | true or false |
m.delete(key), m.size | removes a pair; counts the pairs |
for (const [key, value] of m) visits the pairs in the order they were added.
Set stores values, each one only once. Adding a value that is already there does nothing.
| Code | Effect |
|---|---|
new Set(list) | a set of the list's values, without repeats |
s.add(x), s.delete(x) | adds or removes a value |
s.has(x), s.size | tests for a value; counts the values |
[...new Set(list)] is the shortest way to remove repeats from a list, keeping the first appearance of each.
Why not always use an object? An object works for a fixed set of named properties. A Map is better when the keys come from data, for three reasons. Any value can be a key, including another object. The keys stay in the order they were added, while an object moves number-like keys to the front. And there are no surprises from properties an object inherits, such as constructor.
// Why a Map can be better than a plain object.
const plain = {};
plain["b"] = 1;
plain[10] = 2;
plain[2] = 3;
console.log(Object.keys(plain)); // number-like keys come first, sorted
const map = new Map([["b", 1], [10, 2], [2, 3]]);
console.log([...map.keys()]); // exactly the order they were added
const seen = new Map();
const card = { id: 1 };
seen.set(card, "opened"); // an object can be a key
console.log(seen.get(card), seen.has({ id: 1 }));Choosing a collection. Use an array for an ordered list, an object for one thing with named properties, a Map for looking values up by key, and a Set for "is this in the group?".
Syntax
const ages = new Map();
ages.set("Mitu", 21);
ages.get("Mitu"); // 21
const seen = new Set([1, 2, 2]);
seen.size; // 2
const unique = [...seen];
Example
// A Map counts visits, and a Set removes repeats.
const pages = ["home", "docs", "home", "blog", "docs", "home"];
const visits = new Map();
for (const page of pages) {
visits.set(page, (visits.get(page) ?? 0) + 1);
}
console.log(visits.get("home"), visits.size, visits.has("shop"));
for (const [page, count] of visits) {
console.log(page, count);
}
const unique = new Set(pages);
console.log(unique.size, [...unique]);Line by line
visitsstarts as an empty Map.- For each page,
visits.get(page) ?? 0gives the count so far, or 0 the first time. setstores the new count, replacing the old one.get,sizeandhasanswer questions directly, with no loop.- The
for...ofloop unpacks each pair, in the order the keys were first added. new Set(pages)throws away the repeats, and spread turns the result into an array.
Expected result
3 3 false
home 3
docs 2
blog 1
3 [ 'home', 'docs', 'blog' ]
In the real world
A Set can hold the IDs of items already shown in a feed, so that nothing appears twice. A Map can act as a cache, storing the result for each question so that it never has to be worked out again. Removing duplicates from a list of emails is a one-line job with a Set.
Common mistakes
- Reading a Map like an object.
m.keyandm["key"]do not read its entries. Usem.get("key"). - Expecting objects with equal contents to match.
{ id: 1 }and another{ id: 1 }are two different keys. - Using
.length. Maps and Sets have.size. - Using
JSON.stringifyon a Map. It gives{}. Convert it first withObject.fromEntries(m)or[...m].
Best practices
- Use
hasinstead ofgetwhenundefinedcould be a stored value, or when a stored 0 would read as false. - Convert to an array with spread when you need
maporfilter. - Reach for a Map when the keys are decided by data, not by you.
Summary
A Map stores key and value pairs with any type of key, in insertion order. A Set keeps one copy of each value. Both answer lookup questions directly, which is much faster than searching an array.
Quick check
Key takeaways
- Use a Set to remove repeats or to ask "have I seen this before?".
- A Map keeps its keys in insertion order and allows any type of key.
- has is far faster than searching a long array.
Practice problems for this lesson
My notes
Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.