Eine HashMap ist ein Container, in dem du Schlüssel-Wert-Paare speichern kannst. In anderen Programmiersprachen wird diese Datenstruktur manchmal als assoziatives Array oder Hash-Tabelle bezeichnet. Die Map enthält eine Menge von Schlüsseln, von denen jeder einem bestimmten Wert zugeordnet ist. Du kannst einen gespeicherten Wert abrufen, indem du den passenden Schlüssel übergibst. Außerdem kannst du Schlüssel und die zugehörigen Werte einfügen und löschen.
HashMap ist eine generische Collection (wie die meisten Collections in der Standardbibliothek) und unterstützt daher eine breite Vielfalt von Typen als Schlüssel, darunter selbst definierte Structs und Tupel. Ihre Werte können von beliebigem Typ sein.
HashMap erstellenEine HashMap erstellst du mit der Funktion HashMap::new(). Das folgende Code-Snippet erstellt eine HashMap, in der Teamnamen Punktzahlen zugeordnet sind.
use std::collections::HashMap;
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
HashMap
Wenn du weißt, dass ein Wert in einer HashMap existiert, kannst du den Index-Operator ([]) verwenden. Um zum Beispiel die Punktzahl des blauen Teams abzurufen, können wir scores["Blue"] schreiben. Existiert das passende Schlüssel-Wert-Paar jedoch nicht in der HashMap, führt diese Operation zu einem Panic.
Neben dem Index-Operator gibt es zwei weitere Möglichkeiten, auf Werte in einer HashMap zuzugreifen. Die erste ist die Methode get:
if let Some(blue_score) = scores.get("Blue") {
println!("Blue scored: {blue_score} \n");
}
get greift auf den Wert zu, der unter dem angeforderten Schlüssel gespeichert ist. Es gibt None zurück, wenn der übergebene Schlüssel nicht in der HashMap existiert, und Some(value), wenn der Schlüssel existiert. Mehr über Options in Rust erfährst du im Option-Konzept.
Die andere Möglichkeit, auf Werte in einer HashMap zuzugreifen, ist die Methode entry. Die Methode entry (oder die Entry-API) gibt eine Referenz auf den Eintrag des Schlüssel-Wert-Paares in der HashMap zurück. Der Eintrag repräsentiert den Zustand dieses Schlüssels im Hash. Existiert der Schlüssel nicht, dann gibt es keinen Wert im Eintrag (und es ist möglich, einen einzufügen).
let mut vote_counter: HashMap<_, usize> = HashMap::new();
let votes = ["Blue", "Red", "Red", "Blue", "Red", "Blue", "Blue"];
for vote in votes {
let count = vote_counter.entry(vote).or_default();
*count += 1;
}
println!("{vote_counter:#?}");
Diese API macht bestimmte gängige Zugriffsmuster sehr bequem; ihr ist ein eigenes Konzept (Entry-API) gewidmet.
HashMaps sind relativ schnell und haben für alle Operationen mit einem einzelnen Schlüssel eine amortisierte konstante Laufzeit (O(1)).
Eine HashMap ist eine generische Datenstruktur, das heißt, sie unterstützt beliebige Typen als Schlüssel und Werte, mit nur einer Einschränkung: Damit ein Typ als Schlüsseltyp verwendet werden kann, muss er zwei Traits implementieren: Eq und Hash. Für den Werttyp gibt es keine Trait-Bounds.