Um HashMap é um contentor que pode ser usado para armazenar pares chave-valor. Noutras linguagens de programação, esta estrutura de dados é por vezes chamada array associativo ou tabela de dispersão. O mapa contém um conjunto de chaves, cada uma associada a um valor específico. O utilizador pode obter um valor armazenado passando a chave adequada. Também pode inserir e eliminar chaves e os valores associados.
HashMap é uma coleção genérica (como a maioria das coleções da biblioteca padrão) e, por isso, suporta uma grande variedade de tipos como chaves, incluindo estruturas e tuplos definidos pelo utilizador. Os seus valores podem ser de qualquer tipo.
HashMap
Um HashMap é criado com a função HashMap::new(). O excerto de código abaixo cria um HashMap com nomes de equipas associados a pontuações.
use std::collections::HashMap;
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
HashMap
Se souberes que um valor existe num HashMap, podes usar o operador de indexação ([]). Para obter a pontuação da equipa azul, por exemplo, podemos usar scores["Blue"]. No entanto, se o par chave-valor adequado não existir no HashMap, esta operação entra em pânico.
Além do operador de indexação, há duas outras formas de aceder a valores armazenados num HashMap. A primeira é usar a função membro get:
if let Some(blue_score) = scores.get("Blue") {
println!("Blue scored: {blue_score} \n");
}
get acede ao valor armazenado para a chave pedida. Devolve None se a chave fornecida não existir no HashMap, e Some(value) se a chave existir. Para saberes mais sobre Option em Rust, consulta o conceito Option.
A outra forma de aceder a valores armazenados num HashMap é usar o método entry. O método entry (ou a API entry) devolve uma referência à entrada do par chave-valor no HashMap. A entrada representa o estado desta chave no HashMap. Se a chave não existir, não há valor na entrada (e permite inserir um).
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:#?}");
Esta API torna certos padrões comuns de acesso muito convenientes; há um conceito inteiro (Entry API) dedicado a ela.
Os HashMap são relativamente rápidos e têm complexidade constante amortizada (O(1)) para todas as operações que envolvem uma única chave.
Um HashMap é uma estrutura de dados genérica, o que significa que suporta tipos arbitrários como chaves e valores, com apenas uma restrição: para um tipo ser usado como tipo de chave, tem de ter uma implementação para dois traits: Eq e Hash. Não há limites de traits no tipo do valor.