Set and Map in JavaScript

Set and Map in JavaScript

Set and Map are data structures introduced in ECMAScript 2015 (ES6) that offer new ways to handle collections of data in JavaScript.

Set

A Set is a collection of unique values, where each value can occur only once.

Creation of a Set

let miSet = new Set();

// O con valores iniciales
let numerosUnicos = new Set([1, 2, 3, 4, 4, 5]); // Set(5) {1, 2, 3, 4, 5}

Main methods of Set

  • add(valor): Add a new element to the Set.
  • delete(valor): Removes a specific item.
  • has(valor): Check if a value exists in the Set.
  • clear(): Removes all elements from the Set.
  • size: Property that returns the number of elements.
miSet.add(1);
miSet.add(2);
miSet.add(2); // Ignorado, ya existe

console.log(miSet.has(1)); // true
console.log(miSet.size); // 2

miSet.delete(1);

Iteration over a Set

miSet.forEach((valor) => console.log(valor));

// O usando for...of
for (let valor of miSet) {
  console.log(valor);
}

Map

A Map is a collection of key-value pairs where the keys can be of any type.

Creation of a Map

let miMap = new Map();

// O con pares clave-valor iniciales
let frutas = new Map([
  ['manzana', 500],
  ['banana', 300],
  ['naranja', 200],
]);

Main methods of Map

  • set(clave, valor): Add or update an item.
  • get(clave): Gets the value associated with a key.
  • delete(clave): Removes an item by its key.
  • has(clave): Check if a key exists.
  • clear(): Delete all the elements.
  • size: Property that returns the number of elements.
miMap.set('nombre', 'Juan');
miMap.set('edad', 30);

console.log(miMap.get('nombre')); // 'Juan'
console.log(miMap.has('edad')); // true
console.log(miMap.size); // 2

miMap.delete('edad');

Iteration over a Map

miMap.forEach((valor, clave) => {
  console.log(`${clave}: ${valor}`);
});

// O usando for...of
for (let [clave, valor] of miMap) {
  console.log(`${clave}: ${valor}`);
}

Key differences between Object and Map

  1. An Object has a prototype, so there are default keys in the map. This does not happen with Map.
  2. The keys of an Object are Strings and Symbols, while in a Map they can be of any type.
  3. You can get the size of a Map easily with the size property.

Use cases

  • Use Set when you need to store unique values of any type.
  • Use Map when you need to map keys to values and maintain the insertion order.
  • Prefer Map over Object when the keys are unknown

Conversions between Array, Set, and Map

From Array to Set and vice versa

// De Array a Set
let array = [1, 2, 3, 3, 4, 5];
let set = new Set(array);
console.log(set); // Set(5) {1, 2, 3, 4, 5}

// De Set a Array
let arrayDeNuevo = [...set];
console.log(arrayDeNuevo); // [1, 2, 3, 4, 5]

From Object to Map and vice versa

// De Object a Map
let obj = { nombre: "Ana", edad: 30 };
let map = new Map(Object.entries(obj));
console.log(map); // Map(2) {"nombre" => "Ana", "edad" => 30}

// De Map a Object
let objDeNuevo = Object.fromEntries(map);
console.log(objDeNuevo); // {nombre: "Ana", edad: 30}

WeakSet and WeakMap

JavaScript also provides WeakSet and WeakMap, which are “weak” versions of Set and Map.

WeakSet

  • It can only contain objects.
  • The references to the objects in the set are weak, which means that if there are no other references to the object, it can be collected by the garbage collector.
  • It is not iterable and does not have a size() method.
let weakSet = new WeakSet();
let obj = {};

weakSet.add(obj);
console.log(weakSet.has(obj)); // true

obj = null; // Ahora el objeto puede ser recolectado por el garbage collector

WeakMap

  • The keys must be objects.
  • The references to the keys are weak.
  • It is not iterable and does not have a size() method.
let weakMap = new WeakMap();
let key = {};

weakMap.set(key, 'valor');
console.log(weakMap.get(key)); // "valor"

key = null; // Ahora la entrada puede ser recolectada por el garbage collector

Advanced use cases

Duplicate removal with Set

let array = [1, 2, 2, 3, 4, 4, 5];
let uniqueArray = [...new Set(array)];
console.log(uniqueArray); // [1, 2, 3, 4, 5]

Use of Map for cache

let cache = new Map();

function expensiveOperation(arg) {
    if (cache.has(arg)) {
        console.log("Usando caché");
        return cache.get(arg);
    }

    console.log("Calculando...");
    let result = /* operación costosa */;
    cache.set(arg, result);
    return result;
}

Implementation of a graph with Map

let graph = new Map();

// Añadir nodos y aristas
graph.set('A', ['B', 'C']);
graph.set('B', ['A', 'D']);
graph.set('C', ['A', 'D']);
graph.set('D', ['B', 'C']);

// Función para obtener vecinos
function getNeighbors(node) {
  return graph.get(node) || [];
}

console.log(getNeighbors('A')); // ['B', 'C']

Performance

In general, operations in Set and Map have O(1) performance for insertion, deletion, and lookup, which makes them very efficient for large datasets.

Conclusion

Set and Map are powerful data structures in JavaScript that offer new ways to handle collections. Set is ideal for storing unique values, while Map is perfect for key-value associations where the keys can be of any type. Here are the key advantages:

  1. Flexibility: Unlike regular objects, Map allows you to use any type of data as a key, including objects and functions.

  2. Performance: Both Set and Map offer O(1) performance for common operations such as insertion, deletion, and search.

  3. Data integrity: Set automatically guarantees the uniqueness of elements, which is useful in many scenarios.

  4. Iteration: Both provide consistent and easy-to-use iteration methods.

  5. Additional functionality: They offer useful methods like has(), delete(), and clear() that simplify common operations.

  6. “Weak” versions: WeakSet and WeakMap provide options for specific use cases where special memory handling is needed.

By mastering these data structures, developers can write cleaner, more efficient, and more expressive code. Set and Map are particularly useful in scenarios such as:

  • Removal of duplicates
  • Cache implementation
  • Management of complex relationships between data
  • Optimization of searches in large data sets

As web applications become more complex and handle larger volumes of data, the effective use of Set and Map becomes increasingly important. Therefore, it is crucial for modern JavaScript developers to understand and utilize these powerful tools in their programming arsenal.