Skip to main content

JavaScript Map and Set Collections

JavaScript's ES6 (ECMAScript 2015) introduced two important collection types that have become essential tools for modern JavaScript development: Map and Set. These collection types provide solutions for common programming scenarios that were previously difficult to handle with just arrays and objects.

Introduction to Maps and Sets​

Before ES6, JavaScript developers primarily used objects ({}) for key-value storage and arrays ([]) for lists. While these structures work well for many cases, they have limitations that Map and Set address.

Let's explore these powerful collection types and see how they can enhance your JavaScript code.

Map Collection​

What is a Map?​

A Map is a collection of key-value pairs where both the keys and values can be of any data type. Unlike regular objects, maps remember the original insertion order of the keys.

Creating a Map​

You can create a new Map and add elements in several ways:

javascript
// Creating an empty Map
const userRoles = new Map();

// Adding key-value pairs
userRoles.set('john', 'admin');
userRoles.set('jane', 'editor');
userRoles.set('bob', 'subscriber');

console.log(userRoles);
// Output: Map(3) { 'john' => 'admin', 'jane' => 'editor', 'bob' => 'subscriber' }

You can also initialize a Map with an array of key-value pairs:

javascript
const userRoles = new Map([
['john', 'admin'],
['jane', 'editor'],
['bob', 'subscriber']
]);

console.log(userRoles);
// Output: Map(3) { 'john' => 'admin', 'jane' => 'editor', 'bob' => 'subscriber' }

Key Map Methods and Properties​

Let's explore the essential Map methods:

Getting and Setting Values​

javascript
const userPreferences = new Map();

// Set values
userPreferences.set('theme', 'dark');
userPreferences.set('fontSize', 16);

// Get values
console.log(userPreferences.get('theme')); // Output: dark
console.log(userPreferences.get('fontSize')); // Output: 16
console.log(userPreferences.get('language')); // Output: undefined (key doesn't exist)

Checking if a Key Exists​

javascript
console.log(userPreferences.has('theme')); // Output: true
console.log(userPreferences.has('language')); // Output: false

Deleting Entries​

javascript
userPreferences.delete('fontSize');
console.log(userPreferences.has('fontSize')); // Output: false
console.log(userPreferences); // Output: Map(1) { 'theme' => 'dark' }

Size Property​

javascript
console.log(userPreferences.size); // Output: 1

Clearing a Map​

javascript
userPreferences.clear();
console.log(userPreferences.size); // Output: 0

Iterating Through a Map​

Maps are iterable, and there are several ways to loop through them:

javascript
const productPrices = new Map([
['apple', 1.2],
['banana', 0.9],
['orange', 1.5]
]);

// Iterate over key-value pairs
for (const [product, price] of productPrices) {
console.log(`${product}: $${price}`);
}
// Output:
// apple: $1.2
// banana: $0.9
// orange: $1.5

// Using forEach
productPrices.forEach((price, product) => {
console.log(`${product}: $${price}`);
});
// Output:
// apple: $1.2
// banana: $0.9
// orange: $1.5

Map-Specific Iteration Methods​

Maps provide specific methods for getting iterators:

javascript
// Get an iterator for keys
const keyIterator = productPrices.keys();
for (const key of keyIterator) {
console.log(key); // Output: apple, banana, orange
}

// Get an iterator for values
const valueIterator = productPrices.values();
for (const value of valueIterator) {
console.log(value); // Output: 1.2, 0.9, 1.5
}

// Get an iterator for key-value pairs
const entryIterator = productPrices.entries();
for (const entry of entryIterator) {
console.log(entry); // Output: ['apple', 1.2], ['banana', 0.9], ['orange', 1.5]
}

Maps vs Objects​

Maps offer several advantages over regular objects:

  1. Keys of any type: Map keys can be any value (including functions, objects, and primitives), while object keys must be strings or symbols.
  2. Size tracking: Maps track their size with the size property; objects require manual counting.
  3. Iteration order: Maps preserve insertion order; regular objects don't guarantee order.
  4. Performance: Maps perform better when keys are frequently added and removed.
javascript
// Using non-string keys in a Map
const userMap = new Map();

const userObject = { name: 'John' };
const userFunction = () => console.log('Hello');

userMap.set(userObject, 'User data');
userMap.set(userFunction, 'Function data');
userMap.set(42, 'Number data');

console.log(userMap.get(userObject)); // Output: User data
console.log(userMap.get(userFunction)); // Output: Function data
console.log(userMap.get(42)); // Output: Number data

Set Collection​

What is a Set?​

A Set is a collection of unique values of any type. Each value can only appear once in a Set.

Creating a Set​

javascript
// Creating an empty Set
const uniqueVisitors = new Set();

// Adding values
uniqueVisitors.add('user1');
uniqueVisitors.add('user2');
uniqueVisitors.add('user1'); // Duplicate, will be ignored

console.log(uniqueVisitors);
// Output: Set(2) { 'user1', 'user2' }

You can also initialize a Set with an array:

javascript
const uniqueTags = new Set(['javascript', 'programming', 'web', 'javascript']);

console.log(uniqueTags);
// Output: Set(3) { 'javascript', 'programming', 'web' }

Key Set Methods and Properties​

Adding and Checking Elements​

javascript
const favoriteColors = new Set();

// Add values
favoriteColors.add('blue');
favoriteColors.add('red');
favoriteColors.add('green');

// Check if a value exists
console.log(favoriteColors.has('blue')); // Output: true
console.log(favoriteColors.has('yellow')); // Output: false

Deleting Elements​

javascript
favoriteColors.delete('red');
console.log(favoriteColors); // Output: Set(2) { 'blue', 'green' }

Size Property​

javascript
console.log(favoriteColors.size); // Output: 2

Clearing a Set​

javascript
favoriteColors.clear();
console.log(favoriteColors.size); // Output: 0

Iterating Through a Set​

Sets are iterable, so you can use methods like forEach or a for...of loop:

javascript
const programmingLanguages = new Set(['JavaScript', 'Python', 'Java', 'C++']);

// Using forEach
programmingLanguages.forEach(lang => {
console.log(`I know ${lang}`);
});
// Output:
// I know JavaScript
// I know Python
// I know Java
// I know C++

// Using for...of
for (const lang of programmingLanguages) {
console.log(`I know ${lang}`);
}

Set Operations​

Sets are great for performing mathematical set operations like union, intersection, and difference:

javascript
const setA = new Set([1, 2, 3, 4]);
const setB = new Set([3, 4, 5, 6]);

// Union: combine all elements from both sets
const union = new Set([...setA, ...setB]);
console.log(union);
// Output: Set(6) { 1, 2, 3, 4, 5, 6 }

// Intersection: elements that exist in both sets
const intersection = new Set([...setA].filter(x => setB.has(x)));
console.log(intersection);
// Output: Set(2) { 3, 4 }

// Difference: elements in setA that are not in setB
const difference = new Set([...setA].filter(x => !setB.has(x)));
console.log(difference);
// Output: Set(2) { 1, 2 }

Practical Applications​

Using Maps for Complex Data Management​

Maps are excellent for scenarios where you need to associate data with specific keys:

javascript
// User session management
const userSessions = new Map();

function createSession(userId, data) {
userSessions.set(userId, {
loggedInAt: new Date(),
data: data,
isActive: true
});
}

function getSessionInfo(userId) {
return userSessions.get(userId) || { error: 'No active session' };
}

createSession('user123', { username: 'johndoe', permissions: ['read', 'write'] });
console.log(getSessionInfo('user123'));
// Output: { loggedInAt: Date object, data: { username: 'johndoe', permissions: ['read', 'write'] }, isActive: true }

Using Sets for Filtering Unique Values​

Sets are perfect for removing duplicates from arrays:

javascript
// Remove duplicates from an array
const messyArray = [1, 2, 3, 1, 4, 2, 5, 1, 4];
const uniqueValues = [...new Set(messyArray)];

console.log(uniqueValues); // Output: [1, 2, 3, 4, 5]

Real-world Example: Cache Implementation with Map​

javascript
class SimpleCache {
constructor(maxSize = 100) {
this.cache = new Map();
this.maxSize = maxSize;
}

set(key, value, timeToLiveMs = 5000) {
// Clear old entries if we reached max size
if (this.cache.size >= this.maxSize) {
const oldestKey = this.cache.keys().next().value;
this.cache.delete(oldestKey);
}

// Set expiration time
const expiresAt = Date.now() + timeToLiveMs;

this.cache.set(key, {
value,
expiresAt
});

// Set timeout to automatically delete the item when it expires
setTimeout(() => {
if (this.cache.has(key) && this.cache.get(key).expiresAt <= Date.now()) {
this.cache.delete(key);
}
}, timeToLiveMs);
}

get(key) {
if (!this.cache.has(key)) {
return undefined;
}

const item = this.cache.get(key);

// Check if the item has expired
if (item.expiresAt <= Date.now()) {
this.cache.delete(key);
return undefined;
}

return item.value;
}
}

// Usage
const cache = new SimpleCache(2);
cache.set('user1', { name: 'John', age: 30 });
console.log(cache.get('user1')); // Output: { name: 'John', age: 30 }

Real-world Example: Tracking Unique Site Visitors with Set​

javascript
class VisitorTracker {
constructor() {
this.dailyVisitors = new Set();
this.weeklyVisitors = new Set();
this.monthlyVisitors = new Set();

// Reset daily visitors at midnight
setInterval(() => {
this.dailyVisitors.clear();
}, 86400000); // 24 hours
}

recordVisit(visitorId) {
this.dailyVisitors.add(visitorId);
this.weeklyVisitors.add(visitorId);
this.monthlyVisitors.add(visitorId);
}

getDailyStats() {
return {
uniqueVisitors: this.dailyVisitors.size,
visitorList: [...this.dailyVisitors]
};
}

getWeeklyStats() {
return {
uniqueVisitors: this.weeklyVisitors.size
};
}
}

// Usage
const tracker = new VisitorTracker();
tracker.recordVisit('user123');
tracker.recordVisit('user456');
tracker.recordVisit('user123'); // Duplicate, will be counted only once

console.log(tracker.getDailyStats().uniqueVisitors); // Output: 2

Summary​

Maps and Sets are powerful collection types in modern JavaScript that significantly enhance how we can structure and manipulate data:

Map Collection:

  • A key-value collection where keys can be any data type
  • Maintains insertion order of elements
  • Provides direct methods for adding, retrieving, and deleting elements
  • Better performance for frequent additions and deletions than objects

Set Collection:

  • A collection of unique values
  • Automatically eliminates duplicates
  • Perfect for operations like unions and intersections
  • Great for testing element membership

Understanding when and how to use these collection types is an essential skill for modern JavaScript development. They provide elegant solutions to common programming problems and can make your code more readable and efficient.

Additional Resources​

To deepen your understanding of JavaScript Maps and Sets:

Exercises​

Test your understanding with these exercises:

  1. Create a function that counts the frequency of each word in a string using a Map.
  2. Write a function that takes two arrays and returns an array containing only the elements that appear in both arrays (using Sets).
  3. Implement a simple shopping cart using a Map where product IDs are keys and quantities are values.
  4. Create a function that removes all duplicates from an array of objects based on a specific property (e.g., remove duplicate users based on their email).
  5. Build a simple tag system that ensures tags are unique and case-insensitive using a Set.


If you spot any mistakes on this website, please let me know at feedback@compilenrun.com. I’d greatly appreciate your feedback! :)