Storia della domanda
Le collezioni HashSet e HashMap sono strutture standard di std::collections, che implementano una rapida ricerca tramite hash. Sono integrate in Rust dalle prime versioni del linguaggio, ma i dettagli interni del loro utilizzo spesso causano difficoltà anche agli sviluppatori esperti a causa del sistema di proprietà.
Problema
La confusione si verifica durante l'inserimento e l'estrazione di elementi (soprattutto se i valori non sono Copy), durante le modifiche alla collezione (prestiti mutabili), e anche durante l'uso di riferimenti come chiavi. Esiste anche un problema con l'implementazione corretta di Eq/Hash per i tipi personalizzati.
Soluzione
Esempio di codice:
use std::collections::HashMap; fn main() { let mut map = HashMap::new(); map.insert("key", 42); if let Some(value) = map.get("key") { println!("Found value: {}", value); } }
Punti chiave:
È possibile ottenere più riferimenti mutabili allo stesso elemento di HashMap?
No, il borrow checker non lo consentirà per evitare violazioni della proprietà.
È possibile usare una lettera di stringa "abc" direttamente come chiave di HashMap<String, V>?
No, si aspetta esattamente String, mentre "abc" è &'static str. È necessaria una conversione: insert("abc".to_string(), val).
È possibile estrarre un valore da HashMap, conservarlo in una variabile separata e continuare a utilizzare HashMap?
Sì, è possibile prendere un riferimento al valore tramite get - ma se si esegue remove (o si estrae via move), HashMap muta, e qualsiasi riferimento precedente diventa non valido.
Tentare di prendere in prestito simultaneamente sia la chiave che il valore, e poi mutare la collezione:
let mut map = HashMap::new(); map.insert("abc".to_string(), 10); let val = map.get("abc"); map.insert("def".to_string(), 20); // errore del borrow checker
Vantaggi:
Svantaggi:
Estrazione di un valore, lavoro solo con la sua copia o il suo clone:
let mut map = HashMap::new(); map.insert("abc".to_string(), 10); if let Some(val) = map.get("abc") { let val = *val; // copiamo map.insert("def".to_string(), 20); // tutto funziona }
Vantaggi:
Svantaggi: