Введение#
Hash Map — это коллекция пар “ключ-значение”, которая позволяет быстро находить значения по ключу. Представьте ее как справочник, где вы моментально получаете нужную информацию.
Создание Hash Map#
HashMap::new()
используется чтобы создать новый пустой HashMap.
Импортируем модуль:
use std::collections::HashMap;
Указание типов ключей и значений#
Требуется явно указать типы используемые для ключа и значения:
use std::collections::HashMap;
fn main() {
let smart_home_devices: HashMap<String, String> = HashMap::new();
println!("Пустой hash map устройств с указанием типов String: {:?}", smart_home_devices);
}
Вывод:
Пустой hash map устройств с указанием типов String: {}
Добавление пар “ключ-значение” с помощью insert
#
После создания HashMap вы можете наполнить его данными с помощью метода insert. Каждый вызов принимает ключ и значение:
let mut smart_home_devices: HashMap<String, String> = HashMap::new();
// Добавляем устройства и их статус
smart_home_devices.insert("гостиная_свет".to_string(), "включен".to_string());
smart_home_devices.insert("спальня_термостат".to_string(), "22°C".to_string());
// Обновляем статус устройства
smart_home_devices.insert("гостиная_свет".to_string(), "выключен".to_string());
println!("Статус устройств: {:?}", smart_home_devices);
Вывод:
Статус устройств: {"гостиная_свет": "выключен", "спальня_термостат": "22°C"}
Важно! чтобы сделать коллекцию изменяемой необходимо добавить mut
Условное добавление с entry
и or_insert
#
Иногда вам нужно добавить элемент только в том случае, если ключ еще не существует. API entry в Rust позволяет проверить наличие ключа и добавить значение только при его отсутствии:
let mut smart_home_devices: HashMap<String, String> = HashMap::new();
// Добавляем устройства, избегая перезаписи
smart_home_devices.entry("кухня_холодильник".to_string())
.or_insert("работает".to_string());
// Попытка добавить статус для существующего устройства не изменит его
smart_home_devices.entry("кухня_холодильник".to_string())
.or_insert("неисправен".to_string());
// Добавим новое устройство
smart_home_devices.entry("гараж_ворота".to_string())
.or_insert("закрыты".to_string());
println!("Статус устройств: {:?}", smart_home_devices);
Доступ к значениям в Hash Map#
Метод get
является основным способом извлечения значений из hash map в Rust:
use std::collections::HashMap;
fn main() {
let mut smart_home_devices = HashMap::new();
// Добавляем устройства
smart_home_devices.insert("гостиная_свет".to_string(), "включен".to_string());
smart_home_devices.insert("спальня_термостат".to_string(), "22°C".to_string());
// Получение статуса существующего устройства
let living_room_light = smart_home_devices.get("гостиная_свет");
println!("Статус света в гостиной: {:?}", living_room_light);
// Получение статуса несуществующего устройства
let garage_door = smart_home_devices.get("гараж_ворота");
println!("Статус ворот гаража: {:?}", garage_door);
}
Вывод:
Статус света в гостиной: Some("включен")
Статус ворот гаража: None
Обработка отсутствующих ключей с помощью сопоставления с образцом#
use std::collections::HashMap;
fn main() {
let mut smart_home_devices = HashMap::new();
smart_home_devices.insert("гостиная_свет".to_string(), "включен".to_string());
// Проверка статуса света
match smart_home_devices.get("гостиная_свет") {
Some(status) => println!("Статус света: {}", status),
None => println!("Статус света не найден"),
}
// Проверка статуса несуществующего устройства
match smart_home_devices.get("кухня_кондиционер") {
Some(status) => println!("Статус кондиционера: {}", status),
None => println!("Статус кондиционера: не найден"),
}
}
Вывод:
Статус света: включен
Статус кондиционера: не найден
Предоставление значений по умолчанию с unwrap_or
#
use std::collections::HashMap;
fn main() {
let mut smart_home_devices = HashMap::new();
smart_home_devices.insert("гостиная_свет".to_string(), "включен".to_string());
let default_light_status = "выключен".to_string();
let default_garage_status = "закрыты".to_string();
// Получение статуса с значением по умолчанию
let living_room_light = smart_home_devices.get("гостиная_свет").unwrap_or(&default_light_status);
let garage_door = smart_home_devices.get("гараж_ворота").unwrap_or(&default_garage_status);
println!("Статус света в гостиной: {}", living_room_light);
println!("Статус ворот гаража: {}", garage_door);
}
Вывод:
Статус света в гостиной: включен
Статус ворот гаража: закрыты
Условное обновление с entry
и and_modify
#
use std::collections::HashMap;
fn main() {
let mut smart_home_devices = HashMap::new();
smart_home_devices.insert("гостиная_свет".to_string(), "включен".to_string());
// Обновление статуса существующего устройства
smart_home_devices.entry("гостиная_свет".to_string())
.and_modify(|status| *status = "выключен".to_string());
// Попытка обновить несуществующее устройство (ничего не произойдет)
smart_home_devices.entry("кухня_кондиционер".to_string())
.and_modify(|status| *status = "работает".to_string());
println!("Обновленные статусы устройств: {:?}", smart_home_devices);
}
Вывод:
Обновленные статусы устройств: {"гостиная_свет": "выключен"}
Практический пример#
Давайте рассмотрим практический пример, связанный с управлением умным домом. Предположим, у нас есть несколько устройств в доме и нам нужно отслеживать их текущий статус. Например, мы хотим знать, включен ли свет в гостиной. Какая температура установлена на термостате в спальне и работает ли кондиционер на кухне. Если статус какого-то устройства неизвестен, мы хотим выводить соответствующее сообщение.
- У нас есть список всех устройств, которые могут быть в доме, включая те, статус которых пока неизвестен.
- Для каждого устройства нужно вывести его название и текущий статус
use std::collections::HashMap;
fn main() {
// Создаем HashMap для хранения статусов устройств
let mut home_device_status: HashMap<String, String> = HashMap::new();
// Добавляем статусы для некоторых устройств
home_device_status.insert("гостиная_свет".to_string(), "включен".to_string());
home_device_status.insert("спальня_термостат".to_string(), "22°C".to_string());
// Список всех устройств, которые нас интересуют
let devices = vec!["гостиная_свет", "спальня_термостат", "кухня_кондиционер"];
// Статус по умолчанию, если устройство не найдено
let default_device_status = "статус неизвестен".to_string();
// Перебираем все устройства и выводим их статус
for device in devices {
let status = home_device_status.get(device).unwrap_or(&default_device_status);
println!("{}: {}", device, status);
}
Вывод:
гостиная_свет: включен
спальня_термостат: 22°C
кухня_кондиционер: статус неизвестен
Почему HashMap так полезен?#
- 🚀 Быстрый доступ к данным
- 🔄 Простота обновления и проверки (относительно для языка rust конечно)
- 🛡️ Безопасность типизации
Заключение#
HashMap предоставляет мощный способ работы с парами “ключ-значение”. Они идеально подходят для задач, требующих быстрого поиска и эффективного управления данными.
Используйте HashMap, когда:
- Вы хотите связать произвольный ключ с произвольным значением.
- Вам нужен кэш.
- Вам нужна мапа без дополнительных функций.