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

В чем разница между Множеством и Массивом?

1.2 Junior🔥 131 комментариев
#Dart

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

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

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

Разница между Множеством (Set) и Массивом (List)

В Dart есть две основные коллекции для хранения наборов данных: List (массив) и Set (множество). Хотя на первый взгляд они похожи, у них есть принципиальные различия в структуре, производительности и применении.

Основные отличия

АспектList (Массив)Set (Множество)
Порядок элементовСохраняетсяНе гарантирован
Дублирующиеся элементыДопускаютсяНе допускаются
Доступ по индексуЕсть (list[0])Нет
Производительность поискаO(n)O(1) в среднем
ПамятьМеньше для упорядоченных данныхБольше на хеширование
ИспользованиеКогда важен порядокКогда нужна уникальность

List (Массив) — упорядоченная коллекция

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

  • Элементы хранятся в определённом порядке
  • Индексация начинается с 0
  • Допускаются дублирующиеся элементы
  • Быстрый доступ по индексу O(1)
  • Поиск элемента занимает O(n)
final numbers = [1, 2, 3, 2, 4];

// Доступ по индексу
print(numbers[0]); // Output: 1
print(numbers[2]); // Output: 3

// Добавление
numbers.add(5);       // [1, 2, 3, 2, 4, 5]
numbers.insert(1, 10); // [1, 10, 2, 3, 2, 4, 5]

// Дублирование разрешено
print(numbers); // [1, 10, 2, 3, 2, 4, 5] — есть две двойки

// Проверка наличия (медленно для больших списков)
print(numbers.contains(3)); // true

// Итерация
for (int num in numbers) {
  print(num);
}

// Индекс элемента
print(numbers.indexOf(2)); // 2 (первое вхождение)

Set (Множество) — неупорядоченная коллекция уникальных элементов

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

  • Элементы уникальны, дублирование автоматически убирается
  • Порядок не гарантирован
  • Нет доступа по индексу
  • Поиск элемента быстрый O(1) в среднем (использует хеширование)
  • Оптимален для проверки наличия
final uniqueNumbers = {1, 2, 3, 2, 4};

// Вывод: {1, 2, 3, 4} — вторая двойка удалилась
print(uniqueNumbers); 

// Нет доступа по индексу!
// print(uniqueNumbers[0]); // Error!

// Добавление
unique Numbers.add(5);      // {1, 2, 3, 4, 5}
unique Numbers.add(2);      // {1, 2, 3, 4, 5} — изменений нет

// Быстрая проверка наличия
print(uniqueNumbers.contains(3)); // true — O(1)
print(uniqueNumbers.contains(10)); // false

// Итерация (порядок не гарантирован)
for (int num in uniqueNumbers) {
  print(num);
}

// Размер
print(uniqueNumbers.length); // 5

Практические примеры использования

Пример 1: Список пользователей (List)

class User {
  final int id;
  final String name;
  
  User(this.id, this.name);
}

// Используем List, так как важен порядок и может быть несколько одинаковых пользователей
final users = <User>[
  User(1, 'Alice'),
  User(2, 'Bob'),
  User(1, 'Alice'), // повтор — OK для List
];

// Доступ по индексу
print(users[0].name); // Alice

// Поиск по индексу
final index = users.indexWhere((u) => u.id == 2);
print(index); // 1

Пример 2: Уникальные теги (Set)

// Теги, которые добавляет пользователь
final tags = <String>{};  // Пустое множество

tags.add('flutter');
tags.add('dart');
tags.add('mobile');
tags.add('flutter'); // дублировка проигнорируется

print(tags); // {flutter, dart, mobile} — только уникальные
print(tags.length); // 3

// Быстрая проверка: есть ли метка
if (tags.contains('flutter')) {
  print('This post is about Flutter');
}

Пример 3: Удаление дубликатов из List

final numbers = [1, 2, 2, 3, 4, 4, 4, 5];

// Способ 1: через Set
final unique = numbers.toSet().toList();
print(unique); // [1, 2, 3, 4, 5]

// Способ 2: используя Set напрямую
final uniqueSet = numbers.toSet();
print(uniqueSet); // {1, 2, 3, 4, 5}

Пример 4: Проверка пересечения наборов

final favoriteFruits = {'apple', 'banana', 'orange'};
final availableFruits = {'apple', 'grape', 'orange', 'mango'};

// Пересечение (какие фрукты в обоих наборах)
final intersection = favoriteFruits.intersection(availableFruits);
print(intersection); // {apple, orange}

// Объединение
final union = favoriteFruits.union(availableFruits);
print(union); // {apple, banana, orange, grape, mango}

// Разница
final difference = availableFruits.difference(favoriteFruits);
print(difference); // {grape, mango}

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

// List: поиск O(n), добавление в конец O(1), вставка O(n)
final list = [1, 2, 3];
list.contains(3); // медленно при большом размере
list.add(4);     // быстро

// Set: поиск O(1), добавление O(1), вставка O(1)
final set = {1, 2, 3};
set.contains(3); // быстро
set.add(4);     // быстро

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

Используй List когда:

  • Важен порядок элементов
  • Нужен доступ по индексу
  • Нужна работа с дубликатами
  • Нужна работа на позициях (insert, remove at index)

Используй Set когда:

  • Нужна уникальность элементов
  • Частые проверки наличия элемента
  • Нужны операции множеств (пересечение, объединение)
  • Порядок не важен
  • Оптимизация памяти при уникальности