История вопроса:
В Rust одной из часто используемых коллекций является HashMap — ассоциативный массив, реализованный хеш-таблицей. Отличие rust-реализации — строгое соблюдение правил владения и безопасности памяти, а также thread-safety только при определённых условиях.
Проблема:
В отличие от других языков с garbage-collection, в Rust любые операции с HashMap (добавление, извлечение, модификация) требуют соблюдать правила владения. Например, нельзя изменять коллекцию, имея активные ссылки на её содержимое. Также возникает вопрос владения при вставке: элементы либо перемещаются, либо клонируются. А при конкурентном доступе есть риск data race.
Решение:
get_mut или entry API.Пример кода:
use std::collections::HashMap; fn main() { let mut map = HashMap::new(); map.insert("key", 10); if let Some(value) = map.get_mut("key") { *value += 1; } println!("{:?}", map.get("key")); }
Ключевые особенности:
Может ли быть одновременный доступ к нескольким элементам HashMap по разным ссылкам?
Нет, Rust не допускает этого через стандартный API: итерация с изменением возможна только по эксклюзивной ссылке на всю HashMap.
Что произойдет при попытке получить мутабельную и немутируемую ссылку на один и тот же элемент?
Компилятор выдаст ошибку за нарушение правил borrow checker: нельзя совместить мутабельное и немутируемое заимствование одного значения.
Работает ли API entry() только для вставки новых элементов?
Нет, через Entry API можно также получать доступ для модификации существующего значения, а не только для вставки.
map.entry("key").and_modify(|v| *v += 1).or_insert(0);
Выдача ссылок на значения HashMap в глобальные переменные без гарантии времени жизни карты.
Плюсы:
Минусы:
Оборачивание HashMap в Arc<Mutex<_>> для использования из нескольких потоков.
Плюсы:
Минусы: