Перейти к основному содержимому
  1. Rust/

Hash Map в Rust

733 слов·4 минут· loading · loading · ·
Rust Dev
Оглавление
about-rust - Эта статья часть цикла.
Часть 13: Эта статья

Введение
#

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, когда:

  • Вы хотите связать произвольный ключ с произвольным значением.
  • Вам нужен кэш.
  • Вам нужна мапа без дополнительных функций.

Официальная документация по hash map

about-rust - Эта статья часть цикла.
Часть 13: Эта статья

Связанные статьи

Rust императивный и функциональный, а также о методе collect
1030 слов·5 минут· loading · loading
Rust Dev
Pattern matсhing
606 слов·3 минут· loading · loading
Rust Dev
Паттерн "Строитель" в Rust
641 слово·4 минут· loading · loading
Rust Dev