JAVASCRIPT • COLLECTIONS AND STRINGS

Map & Set — Use Map and Set for key/value and membership (intro)

Learn how Map stores key-value pairs and Set tracks unique values for cleaner, faster JavaScript code.

Historical Context & Motivation

Before Map and Set arrived in JavaScript, developers had only one tool for grouping data under keys: the plain object ({}). While objects work fine for simple cases, they were never designed to be general-purpose dictionaries. Keys had to be strings (or Symbols), there was no built-in way to count entries, and prototype properties could accidentally collide with your data. As web applications grew larger and more complex, these limitations became a real source of bugs.

Similarly, checking whether a value was "already in the collection" meant scanning an array with indexOf or building awkward objects where every value was stored as a key mapped to true. Neither approach was elegant or fast. The JavaScript community needed purpose-built data structures for these two extremely common tasks: associating keys with values and tracking membership in a group of unique items.

1995
JavaScript Is Born
Brendan Eich creates JavaScript in 10 days at Netscape. Plain objects ({}) are the only way to map keys to values.
2009
ES5 Standardized
ES5 adds JSON and strict mode, but still no dedicated Map or Set structures. Developers rely on libraries like Underscore.js for collection utilities.
2011
Early Proposals
TC39 (the committee that designs JavaScript) drafts proposals for Map and Set, inspired by similar structures in Python, Java, and C++.
2015
ES6 (ES2015) Ships Map & Set
The landmark ES6 specification introduces Map, Set, WeakMap, and WeakSet as built-in keyed collections.
2020+
Widespread Adoption
Map and Set are supported in all modern browsers and Node.js. They appear routinely in frameworks like React, Vue, and server-side JavaScript.

The central question that Map and Set answer is straightforward: How can JavaScript give developers fast, flexible collections that go beyond what plain objects and arrays offer? The rest of this lesson explores that answer.

Core Principles & Definitions

At the heart of this topic are two built-in classes that each solve a distinct problem. A Map is a collection of key-value pairs where any data type—strings, numbers, objects, even functions—can serve as a key. A Set is a collection of unique values, meaning it automatically prevents duplicates. Together they cover two of the most common needs in programming: looking something up by a key and checking whether something is already in a group.

1

Any-Type Keys (Map)

Unlike plain objects, a Map lets you use objects, numbers, booleans, or any value as a key—not just strings.
2

Guaranteed Uniqueness (Set)

Adding a duplicate value to a Set is silently ignored, keeping every element unique without extra code.
3

Insertion-Order Iteration

Both Map and Set remember the order you added entries, so looping through them always follows insertion order.
4

Built-in Size Property

Both provide a .size property that instantly returns the number of entries—no manual counting needed.
5

Fast Lookups

Checking if a key exists in a Map or a value exists in a Set is an O(1) operation on average, much faster than searching an array.
✦ KEY TAKEAWAY
Think of a Map like a phone's contact list: each contact name (key) points to a phone number (value), and you can look up anyone instantly. A Set is like a guest list at a party: it only cares whether a name is on the list or not—no duplicates allowed, and it doesn't store extra info for each name.

Visual Explanation

Left: a Map stores key-value pairs where keys can be any type (strings, numbers, objects). Right: a Set stores unique values and silently ignores duplicate additions.

In the diagram above, notice that the Map's keys include a string, a number, and even an object reference—something a plain JavaScript object cannot do. On the Set side, the value "a" is only stored once; attempting to add it again has no effect. Both structures expose a .size property and fast lookup methods (.get() for Map, .has() for Set) that return results in constant time on average.

How Map & Set Work Under the Hood

JavaScript engines implement Map and Set using a technique called hash tables (sometimes combined with linked lists for ordering). When you call map.set(key, value), the engine computes a hash of the key—a numeric fingerprint—that points to a slot in an internal array. This is what makes lookups so fast: instead of scanning every entry, the engine jumps directly to the right slot.

Map API at a Glance

Common Map methods and properties
Method / PropertyWhat It DoesReturns
new Map()Creates an empty MapMap instance
.set(key, val)Adds or updates a key-value pairThe Map itself (chainable)
.get(key)Retrieves the value for a keyThe value, or undefined
.has(key)Checks if a key existstrue or false
.delete(key)Removes a key-value pairtrue if the key existed
.sizeReturns the number of entriesA number
.clear()Removes all entriesundefined

Set API at a Glance

Common Set methods and properties
Method / PropertyWhat It DoesReturns
new Set()Creates an empty SetSet instance
.add(value)Adds a value (ignores duplicates)The Set itself (chainable)
.has(value)Checks if a value existstrue or false
.delete(value)Removes a valuetrue if the value existed
.sizeReturns the number of valuesA number
.clear()Removes all valuesundefined
⚠️ Equality Rules
Map and Set use an algorithm called SameValueZero to compare keys/values. It works like === with one exception: NaN is considered equal to NaN. Two different objects are never equal, even if they have the same properties.

Map vs. Object & Set vs. Array

A natural question is: "Why not just use a plain object or an array?" The answer depends on your use case. The diagrams and table below highlight the key differences so you can make an informed choice.

Top row compares Object vs. Map for key-value storage. Bottom row compares Array vs. Set for membership checking. ✓ = advantage, ✗ = limitation, ~ = partial.

The diagram makes the trade-offs clear. Choose a Map when you need non-string keys, frequent additions and deletions, or a reliable .size. Choose a Set when you need to eliminate duplicates or quickly test whether a value is in your collection. Stick with plain objects for simple config-style data and arrays when you need indexed, ordered data with rich transformation methods.

Worked Example — Counting Word Frequencies

Let's walk through a realistic problem: given a sentence, count how many times each word appears using a Map, and collect the unique words using a Set.

Word Frequency Counter
1
Step 1 — Split the sentence into wordsStart with a sample sentence and split it into an array of lowercase words using .toLowerCase().split(" ").
const words = "the cat sat on the mat".toLowerCase().split(" "); → ["the", "cat", "sat", "on", "the", "mat"]
2
Step 2 — Create a Map to store frequenciesInitialize an empty Map. Loop through each word: if the Map already has that word as a key, increment its count by 1. Otherwise, set its count to 1.
const freq = new Map(); for (const w of words) { freq.set(w, (freq.get(w) || 0) + 1); }
3
Step 3 — Inspect the MapAfter the loop, the Map contains each unique word as a key and its count as the value. The word "the" appears twice, while all other words appear once.
freq.get("the") // → 2 freq.get("cat") // → 1 freq.size // → 5
4
Step 4 — Create a Set of unique wordsPass the array directly into the Set constructor. Duplicates are automatically removed.
const unique = new Set(words); // Set {"the", "cat", "sat", "on", "mat"} unique.size // → 5
5
Step 5 — Convert Set back to an Array (if needed)Use the spread operator or Array.from() to turn the Set back into a regular array for further processing.
const uniqueArr = [...unique]; // ["the", "cat", "sat", "on", "mat"]
💡 PATTERN TO REMEMBER
The expression (map.get(key) || 0) + 1 is a classic JavaScript pattern for counting. If the key doesn't exist yet, .get() returns undefined, which is falsy, so || 0 provides a default of zero before adding one.

Strengths & Limitations

Map & Set: Strengths vs. Limitations
FeatureStrengthLimitation
Key flexibility (Map)Any value—objects, functions, primitives—can be a keyTwo different object references that look identical are treated as different keys
Uniqueness (Set)Automatic deduplication with no extra logicCannot store two objects with the same content—they must be the same reference
PerformanceO(1) average time for add, get, has, and delete operationsSlightly more memory overhead than plain arrays for small collections
IterationGuaranteed insertion-order; works with for...of and forEachNo direct index access (no map[0]) — must iterate or convert to array
SerializationCan be converted to arrays easily via spread or Array.fromJSON.stringify does not work directly — you must convert first
🎯 WHEN TO REACH FOR MAP & SET
Use a Map whenever you need a dictionary with non-string keys, frequent additions/removals, or a reliable count of entries. Use a Set whenever you need to track "have I seen this before?" or remove duplicates from a list. For simple, static config objects or ordered indexed data, plain objects and arrays still work great.

Connection to Advanced Structures

Map and Set are the foundational keyed collections in JavaScript, but ES6 also introduced their "weak" counterparts: WeakMap and WeakSet. Understanding the standard versions prepares you for these more advanced structures.

Standard vs. Weak collections
FeatureMap / SetWeakMap / WeakSet
Key / value typesAny value can be a key (Map) or member (Set)Keys (WeakMap) / members (WeakSet) must be objects or symbols
Garbage collectionEntries persist as long as the Map/Set existsEntries are garbage-collected if no other reference to the key/value exists
Iterable?Yes — supports for...of, .forEach, spreadNo — cannot iterate or check .size
Use caseGeneral-purpose dictionaries and membership trackingPrivate metadata on objects without preventing garbage collection

As you continue in JavaScript, you'll also encounter libraries that build on these primitives. For example, the Immutable.js library provides persistent data structures with Map and Set semantics that never mutate in place. Frameworks like React use Sets internally to track which components need re-rendering. Mastering the built-in Map and Set gives you a strong foundation for all of these tools.

Practice Problems

PROBLEM 1 — CONCEPTUAL
Explain in your own words why you might choose a Map over a plain JavaScript object. Give at least two reasons.
PROBLEM 2 — BASIC CALCULATION
What will the following code output? Trace through it step by step. const s = new Set([3, 1, 4, 1, 5, 9, 2, 6, 5, 3]); console.log(s.size); console.log(s.has(4)); console.log(s.has(7));
PROBLEM 3 — INTERMEDIATE
Write a function countChars(str) that takes a string and returns a Map where each key is a character and each value is the number of times that character appears. For example, countChars("hello") should return a Map with entries: h→1, e→1, l→2, o→1.
PROBLEM 4 — APPLIED
You're building a social media app and need to track which users have liked a post. Each user can only like a post once. If a user tries to like a post again, their like should be removed (toggle behavior). Which data structure would you use and why? Write a function toggleLike(likes, userId) that implements this.
PROBLEM 5 — CRITICAL THINKING
Consider the code below. Why does the second .has() return false, even though the objects look identical? How would you redesign this to make it work? const m = new Map(); m.set({ name: "Alice" }, 100); console.log(m.has({ name: "Alice" })); // false

Lesson Summary

JavaScript's Map is a collection of key-value pairs that accepts any data type as a key, provides a built-in .size property, and guarantees insertion-order iteration. Use .set() to add entries, .get() to retrieve values, and .has() to check for a key—all in O(1) average time.

JavaScript's Set stores unique values and automatically rejects duplicates. It is perfect for membership testing (.has()) and deduplication (pass an array to new Set(arr)). Both Map and Set compare entries using SameValueZero, meaning objects are compared by reference—keep this in mind to avoid subtle bugs. Together, these two collections fill the gaps that plain objects and arrays leave, making your JavaScript code cleaner, faster, and more expressive.

Varsity Tutors • JavaScript • Map & Set — Use Map and Set for key/value and membership (intro)