Historia pytania
Kolekcje HashSet i HashMap to standardowe struktury z std::collections, które implementują szybkie wyszukiwanie na podstawie hasha. Są wbudowane w Rust od pierwszych wersji języka, ale wewnętrzne szczegóły ich użycia często stają się problematyczne nawet dla doświadczonych programistów z powodu systemu własności.
Problemy
Pojawiają się nieporozumienia przy dodawaniu i wyciąganiu elementów (szczególnie jeśli wartości nie są Copy), przy zmianach w kolekcji (nawiasy mutowalne) oraz przy używaniu odniesień jako kluczy. Jest także problem z implementacją poprawnych Eq/Hash dla typów użytkowników.
Rozwiązanie
Przykład kodu:
use std::collections::HashMap; fn main() { let mut map = HashMap::new(); map.insert("key", 42); if let Some(value) = map.get("key") { println!("Znaleziono wartość: {}", value); } }
Kluczowe cechy:
Czy można uzyskać kilka mutowalnych referencji do tego samego elementu HashMap?
Nie, kontroler pożyczek tego nie zezwoli, aby uniknąć naruszenia własności.
Czy można używać literału ciągu "abc" bezpośrednio jako klucza HashMap<String, V>?
Nie, oczekiwany jest dokładnie String, a "abc" to &'static str. Wymagana jest konwersja: insert("abc".to_string(), val).
Czy można wyciągnąć wartość z HashMap, zachowując ją w osobnej zmiennej i kontynuować używanie HashMap?
Tak, można wziąć referencję do wartości przez get — ale jeśli wykonać remove (lub wyciągnąć przez move), HashMap mutuje, a wszelkie wcześniejsze referencje stają się nieważne.
Próba pożyczania jednocześnie klucza i wartości, a następnie modyfikacja kolekcji:
let mut map = HashMap::new(); map.insert("abc".to_string(), 10); let val = map.get("abc"); map.insert("def".to_string(), 20); // błąd kontrolera pożyczek
Zalety:
Wady:
Wyciąganie wartości, praca tylko z jej kopią lub klonem:
let mut map = HashMap::new(); map.insert("abc".to_string(), 10); if let Some(val) = map.get("abc") { let val = *val; // kopiujemy map.insert("def".to_string(), 20); // wszystko działa }
Zalety:
Wady: