Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Map в Dart: Полный гайд
Определение
Map — это коллекция данных, которая хранит пары ключ-значение (key-value pairs). Map — это один из основных data structure'ов в Dart, наряду со List и Set.
// Простой пример
Map<String, int> ages = {
'John': 25,
'Jane': 28,
'Bob': 35,
};
print(ages['John']); // 25
print(ages['Jane']); // 28
Создание Map
1. Литерал синтаксис (рекомендуется)
// С типизацией
Map<String, String> user = {
'name': 'Alice',
'email': 'alice@example.com',
'city': 'New York',
};
// Без типизации (не рекомендуется)
var user = {
'name': 'Alice',
'email': 'alice@example.com',
};
// С неоднородными типами (Map<dynamic, dynamic>)
Map<dynamic, dynamic> mixed = {
'name': 'Alice',
'age': 30,
'verified': true,
};
2. Конструктор
// Пустой Map
Map<String, int> empty = Map();
Map<String, int> empty2 = {};
// Map с начальными данными
var numbers = Map<String, int>.from({'a': 1, 'b': 2});
// Из другого Map
var copy = Map.from(original);
// fromEntries (новый синтаксис)
var map = Map.fromEntries([
MapEntry('a', 1),
MapEntry('b', 2),
]);
3. Динамическое построение
var config = <String, dynamic>{};
config['host'] = 'localhost';
config['port'] = 8080;
config['debug'] = true;
print(config); // {host: localhost, port: 8080, debug: true}
Основные операции
Доступ к элементам
var user = {
'name': 'John',
'age': 30,
};
// Получить значение
print(user['name']); // John
// С безопасностью (может быть null)
print(user['email']); // null (нет ошибки!)
// С default value
print(user['email'] ?? 'no-email'); // no-email
// Проверить наличие ключа
if (user.containsKey('name')) {
print('Name exists');
}
// Получить все ключи
print(user.keys); // (name, age)
// Получить все значения
print(user.values); // (John, 30)
Изменение элементов
var user = {'name': 'John'};
// Добавить или обновить
user['age'] = 30;
user['name'] = 'Jane'; // Обновить
print(user); // {name: Jane, age: 30}
// putIfAbsent (добавить если ключ не существует)
user.putIfAbsent('city', () => 'New York');
user.putIfAbsent('name', () => 'Alice'); // Не заменит
print(user); // {name: Jane, age: 30, city: New York}
Удаление элементов
var user = {'name': 'John', 'age': 30, 'city': 'NY'};
// Удалить один элемент
user.remove('age');
print(user); // {name: John, city: NY}
// Удалить по условию
user.removeWhere((key, value) => value == 'NY');
print(user); // {name: John}
// Очистить весь Map
user.clear();
print(user); // {}
Итерация по Map
forEach
var user = {'name': 'John', 'age': 30};
user.forEach((key, value) {
print('$key: $value');
});
// Output:
// name: John
// age: 30
for-in с entries
var user = {'name': 'John', 'age': 30};
for (var entry in user.entries) {
print('${entry.key}: ${entry.value}');
}
for-in с keys
for (var key in user.keys) {
print('$key = ${user[key]}');
}
Методы Map
map() — трансформировать значения
var ages = {'John': 25, 'Jane': 28};
// Преобразовать значения
var doubled = ages.map((key, value) => MapEntry(key, value * 2));
print(doubled); // {John: 50, Jane: 56}
// Только значения
var newAges = ages.values.map((age) => age + 1).toList();
print(newAges); // [26, 29]
where() — фильтровать
var ages = {'John': 25, 'Jane': 28, 'Bob': 17};
// Взрослые (age >= 18)
var adults = ages.entries
.where((entry) => entry.value >= 18)
.toList();
print(adults); // [MapEntry(John, 25), MapEntry(Jane, 28)]
// Конвертировать обратно в Map
var adultMap = Map.fromEntries(adults);
print(adultMap); // {John: 25, Jane: 28}
update() — обновить значение
var user = {'name': 'John', 'age': 30};
// Обновить если ключ существует
user.update('age', (old) => old + 1);
print(user); // {name: John, age: 31}
// updateAll — обновить все значения
var numbers = {'a': 1, 'b': 2, 'c': 3};
numbers.updateAll((key, value) => value * 10);
print(numbers); // {a: 10, b: 20, c: 30}
addAll() — объединить Map
var map1 = {'a': 1, 'b': 2};
var map2 = {'c': 3, 'd': 4};
map1.addAll(map2);
print(map1); // {a: 1, b: 2, c: 3, d: 4}
// Spread operator (для нового Map)
var merged = {...map1, ...map2};
print(merged); // {a: 1, b: 2, c: 3, d: 4}
Практические примеры
1. JSON (наиболее частый случай)
import 'dart:convert';
// JSON string → Map
var jsonString = '{"name":"John","age":30}';
var map = jsonDecode(jsonString); // Map<String, dynamic>
print(map['name']); // John
print(map['age']); // 30
// Map → JSON string
var user = {'name': 'John', 'age': 30};
var json = jsonEncode(user); // '{"name":"John","age":30}'
2. REST API response
Future<Map<String, dynamic>> fetchUser(String id) async {
final response = await http.get(Uri.parse('https://api.example.com/users/$id'));
if (response.statusCode == 200) {
return jsonDecode(response.body) as Map<String, dynamic>;
}
throw Exception('Failed to load user');
}
// Использование
var user = await fetchUser('1');
print(user['name']);
print(user['email']);
3. Configuration object
class AppConfig {
final Map<String, dynamic> _config;
AppConfig(this._config);
String? getString(String key, [String? defaultValue]) {
return _config[key] ?? defaultValue;
}
int getInt(String key, [int? defaultValue]) {
return _config[key] ?? defaultValue;
}
bool getBool(String key, [bool defaultValue = false]) {
return _config[key] ?? defaultValue;
}
}
// Использование
var config = AppConfig({
'apiUrl': 'https://api.example.com',
'timeout': 30,
'debug': true,
});
print(config.getString('apiUrl')); // https://api.example.com
print(config.getInt('timeout')); // 30
print(config.getBool('debug')); // true
4. Кеширование данных
class Cache<K, V> {
final Map<K, V> _data = {};
V? get(K key) => _data[key];
void set(K key, V value) => _data[key] = value;
bool has(K key) => _data.containsKey(key);
void clear() => _data.clear();
int get size => _data.length;
}
// Использование
final cache = Cache<String, String>();
cache.set('user_1', 'John');
print(cache.get('user_1')); // John
print(cache.has('user_1')); // true
Типичные ошибки
❌ Ошибка 1: Забыть что Map может содержать null
var user = {'name': 'John'};
String name = user['email']!; // ❌ Runtime error!
// Нет ключа 'email', вернется null
✅ Правильно:
String email = user['email'] ?? 'no-email';
String? email = user['email']; // или nullable
❌ Ошибка 2: Изменить Map во время итерации
var map = {'a': 1, 'b': 2, 'c': 3};
for (var key in map.keys.toList()) { // ← toList() ВАЖНО!
if (key == 'b') {
map.remove(key);
}
}
❌ Ошибка 3: Неправильная типизация
Map<String, int> numbers = {'a': 1, 'b': 2};
numbers['c'] = 'three'; // ❌ Type error!
Сравнение Map vs List
| Операция | Map | List |
|---|---|---|
| Поиск по ключу | O(1) | O(n) |
| Добавление | O(1) | O(1)* |
| Удаление | O(1) | O(n) |
| Порядок | Нет гарантии | Гарантированный |
| Наличие дубликатов | Ключи уникальны | Могут быть |
| Использование | Настройки, JSON | Последовательности |
Итоги
Map в Dart:
- Коллекция key-value пар для быстрого поиска
- Основной способ работы с JSON в Dart
- О(1) поиск по ключу (очень быстро)
- Динамическая типизация возможна, но типизация предпочтительна
- Множество методов для трансформации (map, where, update)
Maps — это неотъемлемая часть Dart программирования. От парсинга JSON до конфигурации приложения, Map везде!