В чем разница между множеством (Set) и массивом (List) в Dart?

Ответ

List и Set — это две основные коллекции в Dart с фундаментальными различиями в семантике и производительности.

List (Список/Массив)

  • Упорядоченная коллекция.
  • Допускает дубликаты элементов.
  • Доступ к элементам по индексу.
    List<String> cities = ['Москва', 'Санкт-Петербург', 'Москва'];
    print(cities); // [Москва, Санкт-Петербург, Москва]
    print(cities[1]); // Санкт-Петербург

Set (Множество)

  • Неупорядоченная коллекция (порядок не гарантируется, если это не LinkedHashSet).
  • Содержит только уникальные элементы. Дубликаты автоматически игнорируются.
  • Быстрая проверка на наличие элемента (contains).
    Set<String> uniqueCities = {'Москва', 'Санкт-Петербург', 'Москва'};
    print(uniqueCities); // {Москва, Санкт-Петербург}
    print(uniqueCities.contains('Москва')); // true (выполняется быстро)
Ключевые отличия и выбор: Критерий List Set
Порядок Сохраняется Не гарантирован
Дубликаты Разрешены Запрещены
Производительность contains() O(n) (медленно) O(1) (быстро)
Типичный use-case Лента сообщений, элементы UI в определённом порядке, очередь задач. Хранение уникальных ID, тегов, проверка принадлежности (например, список избранного).

Пример в контексте Flutter:

// List: для отображения упорядоченного списка виджетов
List<Widget> widgetList = [Text('A'), Text('B'), Text('A')];

// Set: для хранения выбранных уникальных элементов в фильтре
Set<int> selectedFilterIds = {1, 5, 1}; // Фактически {1, 5}
if (selectedFilterIds.contains(5)) { ... } // Быстрая проверка

Ответ 18+ 🔞

А, ну вот, опять про эти ваши коллекции. Слушай, тут всё просто, как три копейки, но если не вникнуть — потом овердохуища проблем будет. Представь, что у тебя есть два ящика для инструментов: один — аккуратный органайзер с пронумерованными отделениями, а второй — просто ведро, куда ты кидаешь всё подряд, но только по одному экземпляру.

Вот List — это тот самый органайзер, упорядоченный. Ты кладёшь туда "молоток", "отвёртку" и снова "молоток" — и они там так и лежат, на своих местах. Порядок важен, и одинаковые штуки — пожалуйста. Нужно достать то, что лежит на третьем месте? Без проблем, обращаешься по индексу.

List<String> cities = ['Москва', 'Санкт-Петербург', 'Москва'];
print(cities); // [Москва, Санкт-Петербург, Москва] — две Москвы, ёпта!
print(cities[1]); // Санкт-Петербург — вот он, второй в очереди.

А теперь Set — это наше ведро "только уникальное". Ты пытаешься закинуть туда "Москву", "Питер" и снова "Москву". А оно тебе: "Мужик, ты чё, Москва уже есть, нахуй она мне вторая?" И выплюнет дубликат. Порядок, в котором вещи лежат в ведре, — это тёмный лес, не рассчитывай. Зато если спросить: "А Москва тут есть?" — оно моментально ответит. Быстро, О(1), а не перебирать всё, как в списке.

Set<String> uniqueCities = {'Москва', 'Санкт-Петербург', 'Москва'};
print(uniqueCities); // {Москва, Санкт-Петербург} — второй Москвы нихуя!
print(uniqueCities.contains('Москва')); // true — и проверка моментальная.

Так когда что использовать? Давай на пальцах:

  • Берёшь List, когда: Тебе важен порядок. Лента новостей, список сообщений в чате, очередь заказов на доставку. Там, где "что было первым, а что вторым" — это важно. Или когда дубликаты — это норма (два одинаковых уведомления, например). Но contains() у него — пиздец медленный, он будет тупо всё подряд перебирать.
  • Хватаешь Set, когда: Тебе похуй на порядок, но важно, чтобы штуки не повторялись. Хэш-таблица, короче. Идеально для хранения уникальных айдишников, тегов у товара, выбранных элементов в фильтре. Нужно быстро проверить, есть ли элемент в коллекции? Set — твой бро, делает это за константное время. Доверия к его порядку — ебать ноль, но за скорость поиска ему можно простить.

Пример из жизни Flutter:

// List: Виджеты в Column или ListView. Они же должны идти в определённом порядке, да?
List<Widget> widgetList = [Text('Заголовок'), Text('Текст'), Divider(), Text('Текст')];

// Set: IDшники выбранных юзеров в групповом чате. Выбрать одного юзера дважды — бред.
Set<int> selectedUserIds = {101, 205, 101}; // По факту останется {101, 205}
if (selectedUserIds.contains(205)) { // Проверка — раз плюнуть
  showSnackBar('Юзер уже выбран, ядрёна вошь!');
}

Короче, запомни: List — для порядка и дублей, Set — для уникальности и быстрого поиска. Не перепутай, а то получится мартышлюшка. Выбрал не ту коллекцию — потом сидишь, оптимизируешь кривой contains в списке на тысячу элементов, и волнение ебать, терпения ноль ебать.