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
Related Resources
Official Documentation
Next Steps
- Callbacks and Asynchronous JavaScript
- Promises: Creation, Chaining, Resolution
- Async/Await: Modern Asynchronous Programming
Comments