Geschichte der Frage
Die Sammlungen HashSet und HashMap sind standardmäßige Strukturen aus std::collections, die eine schnelle Suche über Hash implementieren. Sie sind seit den ersten Versionen der Sprache Rust integriert, aber die inneren Details ihrer Nutzung verursachen oft Schwierigkeiten, selbst bei erfahrenen Entwicklern, aufgrund des Eigentumssystems.
Problem
Verwirrung tritt beim Einfügen und Abrufen von Elementen auf (insbesondere wenn Werte nicht Copy sind), bei Änderungen an der Sammlung (mutable Borrowing) sowie bei der Verwendung von Referenzen als Schlüsseln. Es gibt auch ein Problem mit der korrekten Implementierung von Eq/Hash für benutzerdefinierte Typen.
Lösung
Beispielcode:
use std::collections::HashMap; fn main() { let mut map = HashMap::new(); map.insert("key", 42); if let Some(value) = map.get("key") { println!("Gefundenes Wert: {}", value); } }
Wichtige Besonderheiten:
Kann man mehrere mutable Referenzen auf dasselbe Element in HashMap erhalten?
Nein, der Borrow-Checker erlaubt dies nicht, um Verletzungen des Eigentums zu vermeiden.
Kann man den String-Literal "abc" direkt als Schlüssel für HashMap<String, V> verwenden?
Nein, es wird genau ein String erwartet, während "abc" - das ist &'static str. Eine Konvertierung ist notwendig: insert("abc".to_string(), val).
Kann man einen Wert aus HashMap extrahieren, ihn in einer separaten Variablen speichern und HashMap weiterhin verwenden?
Ja, man kann eine Referenz auf den Wert über get nehmen - aber wenn man remove (oder ihn durch move extrahiert), dann verändert sich HashMap und alle alten Referenzen werden ungültig.
Der Versuch, gleichzeitig sowohl den Schlüssel als auch den Wert auszuleihen und dann die Sammlung zu mutieren:
let mut map = HashMap::new(); map.insert("abc".to_string(), 10); let val = map.get("abc"); map.insert("def".to_string(), 20); // Fehler vom Borrow-Checker
Vorteile:
Nachteile:
Extraktion eines Wertes, Arbeiten nur mit seiner Kopie oder Klon:
let mut map = HashMap::new(); map.insert("abc".to_string(), 10); if let Some(val) = map.get("abc") { let val = *val; // kopieren map.insert("def".to_string(), 20); // alles funktioniert }
Vorteile:
Nachteile: