← Назад к вопросам

В чём разница между set и map?

2.0 Middle🔥 131 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между Set и Map в JavaScript

Set и Map - это две важные коллекции данных в современном JavaScript, введенные в стандарт ES6. Хотя они похожи по структуре, они служат разным целям и имеют существенные различия. Давайте разберемся в деталях.

Set

Set - это коллекция уникальных значений. Каждое значение может появиться в Set только один раз.

// Создание Set
const numbers = new Set([1, 2, 3, 3, 4, 4, 5]);
console.log(numbers); // Set { 1, 2, 3, 4, 5 }
// Дубликаты автоматически удалены

const fruits = new Set();
fruits.add("яблоко");
fruits.add("банан");
fruits.add("яблоко"); // Не добавится, уже есть
console.log(fruits); // Set { яблоко, банан }
console.log(fruits.size); // 2

Характеристики Set

1. Хранит только значения

const set = new Set();
set.add("значение");
// Set хранит только значение, без ключа

2. Значения должны быть уникальными

const set = new Set([1, 2, 2, 3, 3, 3]);
console.log(set.size); // 3, а не 6
// Дубликаты игнорируются

3. Сравнение по значению (строгое сравнение)

const set = new Set();
set.add(1);
set.add("1");
console.log(set.size); // 2, так как 1 !== "1" (разные типы)

const obj1 = { id: 1 };
const obj2 = { id: 1 };
const set2 = new Set([obj1, obj2]);
console.log(set2.size); // 2, так как это разные объекты

4. Методы Set

const set = new Set([1, 2, 3]);

// add(value) - добавить элемент
set.add(4);

// has(value) - проверить наличие
console.log(set.has(2)); // true

// delete(value) - удалить элемент
set.delete(2);
console.log(set.has(2)); // false

// clear() - очистить все элементы
set.clear();
console.log(set.size); // 0

// Итерация
for (const value of set) {
  console.log(value);
}

Map

Map - это коллекция пар ключ-значение. Похож на объект, но с дополнительными возможностями.

// Создание Map
const userMap = new Map();
userMap.set("user1", { name: "Иван", age: 30 });
userMap.set("user2", { name: "Мария", age: 25 });

console.log(userMap);
// Map {
//   user1 => { name: Иван, age: 30 },
//   user2 => { name: Мария, age: 25 }
// }

console.log(userMap.size); // 2

Характеристики Map

1. Хранит пары ключ-значение

const map = new Map();
map.set("name", "Иван");
map.set("age", 30);
map.set("city", "Москва");

// Каждый ключ связан с значением

2. Ключ может быть любого типа

const map = new Map();

// String как ключ
map.set("name", "Иван");

// Number как ключ
map.set(1, "первый");

// Object как ключ (!)
const obj = { id: 1 };
map.set(obj, "значение");

// Function как ключ
const func = () => {};
map.set(func, "функция");

console.log(map.size); // 4

3. Это очень важное отличие от объектов!

// С объектом
const obj = {};
obj[{ id: 1 }] = "значение1";
obj[{ id: 1 }] = "значение2"; // Перезапишет
console.log(Object.keys(obj)); // ["[object Object]"] - потеря информации

// С Map
const map = new Map();
const key1 = { id: 1 };
const key2 = { id: 1 };
map.set(key1, "значение1");
map.set(key2, "значение2"); // Оба сохранены!
console.log(map.size); // 2

4. Методы Map

const map = new Map();
map.set("a", 1);
map.set("b", 2);
map.set("c", 3);

// get(key) - получить значение
console.log(map.get("a")); // 1

// has(key) - проверить наличие ключа
console.log(map.has("b")); // true

// delete(key) - удалить пару
map.delete("b");

// clear() - очистить все
map.clear();

// Итерация по ключам
for (const key of map.keys()) {
  console.log(key);
}

// Итерация по значениям
for (const value of map.values()) {
  console.log(value);
}

// Итерация по парам
for (const [key, value] of map.entries()) {
  console.log(key, value);
}

Сравнительная таблица

ХарактеристикаSetMap
ХранитЗначенияПары ключ-значение
УникальностьЗначения уникальныКлючи уникальны
Тип ключаN/AЛюбой тип
Методыadd, has, delete, clearset, get, has, delete, clear
Итерацияfor...of, forEachfor...of, forEach
Размер.size.size
Приоритет использованияУникальные значенияСвязанные данные

Практические примеры

Пример 1: Set для удаления дубликатов

// Задача: удалить дубликаты из массива
const numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5];
const unique = [...new Set(numbers)];
console.log(unique); // [1, 2, 3, 4, 5]

// Работает с любыми типами
const words = ["яблоко", "банан", "яблоко", "груша"];
const uniqueWords = [...new Set(words)];
console.log(uniqueWords); // [яблоко, банан, груша]

Пример 2: Set для проверки членства

// Вместо: array.includes() который O(n)
const allowedRoles = ["admin", "moderator", "user"];
function checkOld(role) {
  return allowedRoles.includes(role); // O(n)
}

// Используем Set - O(1)
const allowedRolesSet = new Set(allowedRoles);
function checkNew(role) {
  return allowedRolesSet.has(role); // O(1), намного быстрее
}

// На миллионе элементов разница ощутима

Пример 3: Set для отслеживания посещений

class WebsiteAnalytics {
  constructor() {
    this.visitedUsers = new Set();
  }
  
  trackVisit(userId) {
    this.visitedUsers.add(userId);
  }
  
  getUniqueVisitors() {
    return this.visitedUsers.size;
  }
  
  hasVisited(userId) {
    return this.visitedUsers.has(userId);
  }
}

const analytics = new WebsiteAnalytics();
analytics.trackVisit("user1");
analytics.trackVisit("user2");
analytics.trackVisit("user1"); // Не считается дважды
console.log(analytics.getUniqueVisitors()); // 2

Пример 4: Map для кэширования

class UserService {
  constructor() {
    this.cache = new Map();
  }
  
  getUser(userId) {
    // Проверяем кэш
    if (this.cache.has(userId)) {
      console.log("Из кэша");
      return this.cache.get(userId);
    }
    
    // Получаем из БД
    const user = this.fetchFromDB(userId);
    
    // Сохраняем в кэш
    this.cache.set(userId, user);
    return user;
  }
  
  fetchFromDB(userId) {
    // Имитация запроса к БД
    return { id: userId, name: "Иван" };
  }
}

const service = new UserService();
console.log(service.getUser(1)); // Из БД
console.log(service.getUser(1)); // Из кэша

Пример 5: Map для связей один-ко-многим

const groupMembers = new Map();

// Группа "frontend"
groupMembers.set("frontend", new Set(["Иван", "Мария", "Петр"]));

// Группа "backend"
groupMembers.set("backend", new Set(["Сергей", "Анна"]));

// Получить всех членов группы
console.log(groupMembers.get("frontend")); // Set { Иван, Мария, Петр }

// Проверить членство
const frontendMembers = groupMembers.get("frontend");
console.log(frontendMembers.has("Иван")); // true

// Добавить нового члена
frontendMembers.add("Александр");

Пример 6: Map для графов

class Graph {
  constructor() {
    this.adjacencyList = new Map();
  }
  
  addVertex(vertex) {
    if (!this.adjacencyList.has(vertex)) {
      this.adjacencyList.set(vertex, new Set());
    }
  }
  
  addEdge(vertex1, vertex2) {
    this.addVertex(vertex1);
    this.addVertex(vertex2);
    this.adjacencyList.get(vertex1).add(vertex2);
    this.adjacencyList.get(vertex2).add(vertex1);
  }
  
  getConnections(vertex) {
    return this.adjacencyList.get(vertex);
  }
}

const graph = new Graph();
graph.addEdge("A", "B");
graph.addEdge("B", "C");
graph.addEdge("A", "C");
console.log(graph.getConnections("A")); // Set { B, C }

Когда использовать Set

  1. Нужны уникальные значения
  2. Нужна быстрая проверка membershipа - O(1)
  3. Нужно удалять дубликаты из массива
  4. Отслеживание посещений, событий
  5. Реализация множеств (union, intersection)

Когда использовать Map

  1. Нужны связи ключ-значение
  2. Ключи - не только строки (объекты, функции)
  3. Нужно хранить мета-информацию о элементах
  4. Кэширование данных
  5. Реализация графов, деревьев, таблиц

Производительность

// Set: проверка membershipа
const set = new Set(Array.from({length: 1000000}, (_, i) => i));
console.time("Set has");
set.has(500000);
console.timeEnd("Set has"); // ~0.1ms - O(1)

// Array: проверка membershipа
const arr = Array.from({length: 1000000}, (_, i) => i);
console.time("Array includes");
arr.includes(500000);
console.timeEnd("Array includes"); // ~2-5ms - O(n)

// Set намного быстрее для больших коллекций!

Заключение

Set - это коллекция уникальных значений, идеальная для удаления дубликатов и быстрой проверки membershipа.

Map - это коллекция пар ключ-значение, идеальная для связи данных и кэширования.

Выбирай Set, когда нужны только значения. Выбирай Map, когда нужны связи между данными. Комбинируй их для сложных структур данных.