Ha

Hashmap em Rust

{one: "1 exercício", many: "%{count} de exercícios", other: "%{count} exercícios"}

Sobre Hashmap

Um HashMap é um contêiner que pode ser usado para armazenar pares chave-valor. Em outras linguagens de programação, essa estrutura de dados às vezes é chamada de array associativo ou tabela hash. O mapa contém um conjunto de chaves, cada uma mapeada para um valor específico. É possível recuperar um valor armazenado passando a chave apropriada. Também dá para inserir e excluir chaves e os valores associados.

HashMap é uma coleção genérica (como a maioria das coleções da biblioteca padrão) e, por isso, aceita uma grande variedade de tipos como chaves, incluindo structs e tuplas definidas pelo usuário. Seus valores podem ser de qualquer tipo.

Criando um HashMap

Um HashMap é criado usando a função HashMap::new(). O trecho de código abaixo cria um HashMap com nomes de times 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);

Acessando valores em HashMap

Se soubermos que um valor existe dentro de um HashMap, usar o operador de indexação ([]) é o mais apropriado. Para recuperar a pontuação do time azul, por exemplo, podemos usar scores["Blue"]. No entanto, se o par chave-valor apropriado não existir no hashmap, essa operação vai causar um panic.

Além do operador de indexação, há duas outras formas de acessar valores armazenados em um HashMap. A primeira é usar a função membro get:

if let Some(blue_score) = scores.get("Blue") {
    println!("Blue scored: {blue_score} \n");
}

get acessa o valor armazenado na chave solicitada. Retorna None se a chave fornecida não existir no HashMap, e Some(value) se ela existir. Para saber mais sobre Options em Rust, veja o conceito Options.

A outra forma de acessar valores armazenados em um HashMap é usar o método entry. O método entry (ou a entry API) retorna uma referência à entrada do par chave-valor no HashMap. A entrada representa o estado dessa chave no hash. Se a chave não existir, então não há valor na entrada (e ela permite que um seja inserido).

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:#?}");

Essa API torna certos padrões de acesso muito convenientes; existe um conceito inteiro (a Entry API) dedicado a ela.

Eficiência

Os HashMaps são relativamente rápidos e têm complexidade de tempo constante amortizada (O(1)) para todas as operações que envolvem uma única chave.

Limites de trait

Um HashMap é uma estrutura de dados genérica, ou seja, aceita tipos arbitrários como chaves e valores, com apenas uma restrição: para que um tipo seja usado como tipo de chave, ele precisa ter uma implementação de dois traits: Eq e Hash. Não há limites de trait no tipo de valor.

Editar via GitHub O link abre em uma nova janela ou aba