Ответ
В Dart я активно использую Map для различных сценариев. Вот основные подходы:
1. Создание и инициализация Map:
// Литерал Map
final Map<String, int> scores = {
'Alice': 100,
'Bob': 85,
'Charlie': 92,
};
// Конструктор
final emptyMap = Map<String, dynamic>();
final fromConstructor = Map.from(scores); // Копия
// Для неизменяемых данных
const constantMap = const {
'apiUrl': 'https://api.example.com',
'timeout': 30,
};
2. Преобразование коллекций в Map:
// Из List в Map
final users = ['Alice', 'Bob', 'Charlie'];
final userMap = Map.fromIterable(
users,
key: (user) => user.toLowerCase(),
value: (user) => User(name: user),
);
// {'alice': User('Alice'), 'bob': User('Bob'), ...}
// Из двух List (ключи и значения)
final keys = ['id', 'name', 'email'];
final values = [1, 'Alice', 'alice@example.com'];
final map = Map.fromIterables(keys, values);
// {'id': 1, 'name': 'Alice', 'email': 'alice@example.com'}
// Из List<MapEntry>
final entries = [
MapEntry('createdAt', DateTime.now()),
MapEntry('updatedAt', DateTime.now()),
];
final fromEntries = Map.fromEntries(entries);
3. Работа с MapEntry:
// Создание Map через entries
final config = Map.fromEntries([
MapEntry('theme', 'dark'),
MapEntry('notifications', true),
MapEntry('language', 'ru'),
]);
// Итерация по entries
config.entries.forEach((entry) {
print('${entry.key}: ${entry.value}');
});
// Фильтрация через entries
final filtered = Map.fromEntries(
config.entries.where((entry) => entry.value != null),
);
4. Полезные методы Map:
final map = {'a': 1, 'b': 2, 'c': 3};
// Проверка и доступ
if (map.containsKey('a')) {
final value = map['a'];
}
// Безопасное получение с значением по умолчанию
final value = map['d'] ?? 0;
final value2 = map.putIfAbsent('d', () => 0);
// Обновление значений
map.update('a', (v) => v + 1);
map.update('d', (v) => v + 1, ifAbsent: () => 1);
// Удаление
map.remove('b');
map.removeWhere((key, value) => value < 2);
// Преобразование
final doubled = map.map((key, value) => MapEntry(key, value * 2));
5. Кастомные Map для специфичных нужд:
// Case-insensitive Map
class CaseInsensitiveMap<K extends String, V> implements Map<K, V> {
final Map<String, V> _map = {};
@override
V? operator [](Object? key) {
return _map[(key as String).toLowerCase()];
}
@override
void operator []=(K key, V value) {
_map[key.toLowerCase()] = value;
}
// ... остальная реализация Map
}
// Использование
final ciMap = CaseInsensitiveMap<String, int>();
ciMap['Hello'] = 1;
print(ciMap['HELLO']); // 1
6. JSON-сериализация (частая задача в Flutter):
// Map ↔ JSON
final map = {'name': 'Alice', 'age': 30};
final jsonString = jsonEncode(map);
final decodedMap = jsonDecode(jsonString) as Map<String, dynamic>;
// Для сложных объектов с json_serializable
@JsonSerializable()
class User {
final String name;
final int age;
User(this.name, this.age);
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
7. LinkedHashMap (дефолтная реализация) vs SplayTreeMap vs HashMap:
// Сохраняет порядок вставки (по умолчанию)
final ordered = LinkedHashMap<String, int>();
// Автоматическая сортировка по ключам
final sorted = SplayTreeMap<String, int>();
sorted['z'] = 1;
sorted['a'] = 2;
print(sorted.keys); // (a, z)
// Не гарантирует порядок, но может быть быстрее
final hashMap = HashMap<String, int>();
В Flutter-разработке Map особенно полезны для конфигурации, кэширования данных, передачи параметров между экранами и работы с JSON API. Я часто использую Map.fromIterable для преобразования списков из API в более удобные для работы структуры.
Ответ 18+ 🔞
А, ну ты глянь, какие тут у нас карты разложены! Я в Dart с Map'ами как рыба в воде, потому что без них нихуя не работает. Вот смотри, как я их обычно юзаю, чтобы не облажаться.
1. Сначала создаём эту штуку, ёпта:
// Самый простой способ, прямо в лоб
final Map<String, int> scores = {
'Alice': 100,
'Bob': 85,
'Charlie': 92,
};
// А если с пустого листа начинать — конструктор в помощь
final emptyMap = Map<String, dynamic>();
final fromConstructor = Map.from(scores); // Сделал копию, и волнение ебать — оригинал не тронул
// Для константных штук, которые ни хуя не должны меняться
const constantMap = const {
'apiUrl': 'https://api.example.com',
'timeout': 30,
};
2. Превращаем одни коллекции в другие, как фокусник, блядь:
// Берём List и — хуяк! — уже Map
final users = ['Alice', 'Bob', 'Charlie'];
final userMap = Map.fromIterable(
users,
key: (user) => user.toLowerCase(),
value: (user) => User(name: user),
);
// Получится {'alice': User('Alice'), 'bob': User('Bob'), ...}
// А если у тебя два списка — ключи отдельно, значения отдельно? Тоже не проблема!
final keys = ['id', 'name', 'email'];
final values = [1, 'Alice', 'alice@example.com'];
final map = Map.fromIterables(keys, values);
// {'id': 1, 'name': 'Alice', 'email': 'alice@example.com'} — красота!
// Ну или через MapEntry, если ты любишь всё контролировать
final entries = [
MapEntry('createdAt', DateTime.now()),
MapEntry('updatedAt', DateTime.now()),
];
final fromEntries = Map.fromEntries(entries);
3. MapEntry — это как кирпичик, из которого карту собираешь:
// Собираем конфиг по кирпичикам
final config = Map.fromEntries([
MapEntry('theme', 'dark'),
MapEntry('notifications', true),
MapEntry('language', 'ru'),
]);
// Потом по ним же и итерируешься
config.entries.forEach((entry) {
print('${entry.key}: ${entry.value}');
});
// Или отфильтровать можешь, если что-то не нравится
final filtered = Map.fromEntries(
config.entries.where((entry) => entry.value != null),
);
4. А вот методы, без которых нихуя не сделаешь, запоминай:
final map = {'a': 1, 'b': 2, 'c': 3};
// Проверяем, есть ли ключ, а то вдруг nil прилетит
if (map.containsKey('a')) {
final value = map['a']; // Теперь спокойно берём
}
// Безопасное получение, чтобы не вылететь в сраку
final value = map['d'] ?? 0; // Если нет — будет ноль
final value2 = map.putIfAbsent('d', () => 0); // Или создай, если нету
// Обновляем значения, как настоящие мужики
map.update('a', (v) => v + 1);
map.update('d', (v) => v + 1, ifAbsent: () => 1); // А если ключа нет — создаст
// Удаляем всё ненужное
map.remove('b');
map.removeWhere((key, value) => value < 2); // Удалит всё, где значение меньше двух
// И даже преобразовать можно
final doubled = map.map((key, value) => MapEntry(key, value * 2));
5. Иногда стандартная карта — как хуй в пальто, неудобно. Делаем свою:
// Например, карта, которой похуй на регистр букв
class CaseInsensitiveMap<K extends String, V> implements Map<K, V> {
final Map<String, V> _map = {};
@override
V? operator [](Object? key) {
return _map[(key as String).toLowerCase()];
}
@override
void operator []=(K key, V value) {
_map[key.toLowerCase()] = value;
}
// ... остальную реализацию Map пишешь тут, это долго, но понятно
}
// Используем
final ciMap = CaseInsensitiveMap<String, int>();
ciMap['Hello'] = 1;
print(ciMap['HELLO']); // 1 — работает, ебать!
6. JSON-сериализация — это вообще святое в Flutter, без неё никуда:
// Просто Map в JSON и обратно
final map = {'name': 'Alice', 'age': 30};
final jsonString = jsonEncode(map);
final decodedMap = jsonDecode(jsonString) as Map<String, dynamic>;
// А для сложных объектов юзаем json_serializable, чтобы не ебаться
@JsonSerializable()
class User {
final String name;
final int age;
User(this.name, this.age);
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
7. И напоследок, ёпта, разные типы Map, чтобы не путаться:
// LinkedHashMap — по умолчанию, порядок вставки помнит
final ordered = LinkedHashMap<String, int>();
// SplayTreeMap — умная, сама сортирует по ключам
final sorted = SplayTreeMap<String, int>();
sorted['z'] = 1;
sorted['a'] = 2;
print(sorted.keys); // (a, z) — видишь, алфавит!
// HashMap — порядок не гарантирует, зато может быть быстрее
final hashMap = HashMap<String, int>();
В общем, в Flutter без Map — как без рук. Конфиги, кэш, параметры между экранами гонять, JSON от API разбирать — везде они. Особенно Map.fromIterable люблю, когда список с бэкенда приходит, а надо его в удобную структуру превратить. Главное — не переусердствовать, а то получится пиздопроебибна, а не код.