Списки, множества и карты
Одна переменная хранит одно значение; коллекция хранит сразу множество — список товаров, набор тегов, словарь настроек.
Суть:
List— упорядоченный список с дубликатами,Set— набор уникальных значений без порядка,Map— пары «ключ — значение». Это три рабочие лошадки любого приложения.
Коллекции в Dart умеют создаваться декларативно прямо внутри литерала. Есть collection if и collection for: можно написать [if (isAdmin) adminButton, for (var t in tags) Chip(t)] — и список соберётся по условию и циклу прямо на месте. Эта возможность бесценна во Flutter, где списки детей виджета часто зависят от данных и флагов. Так данные превращаются в интерфейс без отдельных циклов снаружи.
Представьте экран со списком задач. Каждая задача — отдельный объект, но их много, и хранить сотню переменных task1, task2 невозможно. Поэтому данные складывают в коллекции. Самая частая — List: упорядоченная последовательность, где у каждого элемента есть индекс, начинающийся с нуля.
List<String> fruits = ['яблоко', 'банан', 'груша'];
print(fruits[0]); // яблоко (индекс с нуля)
print(fruits.length); // 3
fruits.add('слива'); // добавить в конец
Set<int> ids = {1, 2, 2, 3}; // дубликат 2 исчезнет
print(ids); // {1, 2, 3}
Map<String, int> ages = {'Аня': 20, 'Боря': 25};
print(ages['Аня']); // 20
ages['Вера'] = 30; // добавить пару
Угловые скобки List<String> — это дженерик: они говорят, что в списке лежат именно строки. Компилятор не даст положить туда число — ещё один уровень защиты от ошибок.
Как выбрать структуру под капотом
Каждая коллекция оптимизирована под свою задачу. List хранит порядок и допускает повторы — идеален для ленты постов. Set мгновенно проверяет, есть ли элемент, и сам выбрасывает дубликаты — идеален для набора уникальных тегов. Map ищет значение по ключу за один шаг — идеален для настроек или кэша.
List [a, b, c, a] порядок есть, дубликаты можно, доступ по индексу
0 1 2 3
Set {a, b, c} порядка нет, дубликатов нет, быстрый contains()
Map {k1: v1, ключ -> значение, быстрый поиск по ключу
k2: v2}
# Аналоги коллекций Dart на Python: list / set / dict
fruits = ['яблоко', 'банан', 'груша']
print(fruits[0], len(fruits)) # доступ по индексу и длина
ids = {1, 2, 2, 3} # дубликат уберётся
print('set:', ids)
ages = {'Аня': 20, 'Боря': 25}
ages['Вера'] = 30 # добавить пару
print('Аня:', ages['Аня'])
print('Есть Боря?', 'Боря' in ages)
Частые ошибки
- Выход за границы списка.
fruits[10]при трёх элементах — ошибка. Индекс последнего элемента всегдаlength - 1. - Ожидать порядок от
Set. Множество не гарантирует порядок — если он важен, беритеList. - Обращаться к несуществующему ключу
Map.ages['Кто-то']вернётnull, а не упадёт — учитывайте это в null-safety.
Best practices
- Всегда указывайте тип элементов:
List<Task>, а не простоList— так вы получаете подсказки и защиту. - Нужна уникальность — берите
Set, не изобретайте проверку дубликатов вручную. - Для неизменяемых наборов используйте
const-коллекции — Flutter их оптимизирует.
При выборе между структурами думайте о главном вопросе к данным. Если вы будете часто спрашивать «есть ли такой элемент?» — берите Set или Map, они отвечают мгновенно. Если важен порядок и индекс — List. Если нужно связать одно с другим (id с объектом, ключ с настройкой) — однозначно Map. Правильно выбранная структура не только ускоряет код, но и делает его намерение очевидным для читающего.
Итог: List, Set и Map покрывают почти все потребности в хранении данных. Выбор правильной структуры — это половина чистого кода; следующая половина — умение её обрабатывать, чем мы займёмся в следующем уроке.