Historia pytania:
W Rust jedna z często używanych kolekcji to HashMap — asocjacyjna tablica zaimplementowana jako tabela haszująca. Różnica w implementacji w Rust polega na ścisłym przestrzeganiu zasad własności i bezpieczeństwa pamięci oraz bezpieczeństwie wątków tylko w określonych warunkach.
Problem:
W przeciwieństwie do innych języków z garbage-collection, w Rust wszelkie operacje na HashMap (dodawanie, wydobycie, modyfikacja) wymagają przestrzegania zasad własności. Na przykład nie można modyfikować kolekcji, mając aktywne odniesienia do jej zawartości. Ponadto pojawia się pytanie o własność przy wstawianiu: elementy są albo przenoszone, albo klonowane. A przy dostępie równoległym istnieje ryzyko data race.
Rozwiązanie:
get_mut lub entry.Przykład kodu:
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")); }
Kluczowe cechy:
Czy może być jednoczesny dostęp do kilku elementów HashMap przez różne odniesienia?
Nie, Rust tego nie dopuszcza przez standardowe API: iteracja z modyfikacją możliwa jest tylko przez wyłączne odniesienie do całej HashMap.
Co się stanie, gdy spróbujesz uzyskać mutowalne i niemutowalne odniesienie do jednego tego samego elementu?
Kompilator zgłosi błąd z powodu naruszenia zasad borrow checkera: nie można połączyć mutowalnego i niemutowalnego pożyczania tej samej wartości.
Czy API entry() działa tylko przy wstawianiu nowych elementów?
Nie, przez API Entry można również uzyskiwać dostęp do modyfikacji istniejącej wartości, a nie tylko do wstawiania.
map.entry("key").and_modify(|v| *v += 1).or_insert(0);
Wydawanie odniesień do wartości HashMap w globalnych zmiennych bez gwarancji czasu życia mapy.
Zalety:
Wady:
Owinięcie HashMap w Arc<Mutex<_>> w celu użycia z kilku wątków.
Zalety:
Wady: