Una HashMap è un contenitore che può essere usato per memorizzare coppie chiave-valore. In altri linguaggi di programmazione, questa struttura dati è talvolta chiamata array associativo o tabella hash. La mappa contiene un insieme di chiavi, ognuna delle quali è associata a un particolare valore. L'utente può recuperare un valore memorizzato passando la chiave appropriata. Gli utenti possono anche inserire ed eliminare chiavi e i valori associati.
HashMap è una collezione generica (come la maggior parte delle collezioni nella libreria standard) e quindi supporta una grande varietà di tipi come chiavi, incluse struct e tuple definite dall'utente. I suoi valori possono essere di qualsiasi tipo.
HashMap
Una HashMap si crea con la funzione HashMap::new(). Il frammento di codice qui sotto crea una HashMap con i nomi delle squadre associati ai punteggi.
use std::collections::HashMap;
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
HashMap
Se si sa che un valore esiste all'interno di una HashMap, allora è appropriato usare l'operatore di indicizzazione ([]). Per recuperare il punteggio della squadra blu, ad esempio, possiamo usare scores["Blue"]. Tuttavia, se la coppia chiave-valore appropriata non esiste all'interno della hashmap, questa operazione provocherà un panic.
Oltre all'operatore di indicizzazione, ci sono altri due modi per accedere ai valori memorizzati in una HashMap. Il primo è usare la funzione membro get:
if let Some(blue_score) = scores.get("Blue") {
println!("Blue scored: {blue_score} \n");
}
get accede al valore memorizzato in corrispondenza della chiave richiesta. Restituisce None se la chiave fornita non esiste nella HashMap, e Some(value) se la chiave esiste. Per ulteriori informazioni sulle Option in Rust, consulta il concetto Options.
L'altro modo per accedere ai valori memorizzati in una HashMap è usare il metodo entry. Il metodo entry (o l'entry API) restituisce un riferimento alla entry della coppia chiave-valore nella HashMap. La entry rappresenta lo stato di questa chiave nella hash. Se la chiave non esiste, allora non c'è alcun valore nella entry (e ne consente l'inserimento di uno).
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:#?}");
Questa API rende molto comodi alcuni pattern di accesso comuni; esiste un intero concetto (Entry API) dedicato ad essa.
Le HashMap sono relativamente veloci e hanno complessità costante ammortizzata (O(1)) per tutte le operazioni che coinvolgono una singola chiave.
Una HashMap è una struttura dati generica, il che significa che supporta tipi arbitrari da usare come chiavi e valori, con un solo vincolo: perché un tipo possa essere usato come tipo di chiave, deve avere un'implementazione per due trait: Eq e Hash. Non ci sono vincoli sui trait per il tipo dei valori.