Le Hash Map in Rust

Vediamo in che modo le hash map ci permettono di organizzare meglio i dati nei nostri progetti fatti con il linguaggio Rust.

Le hash map ci permettono di raccogliere dati formati da coppie chiave-valore. Una sorta di dizionario dove ad ogni chiave può corrispondere una descrizione ma anche altri tipi di dato.

Ad esempio, possiamo creare istanze di una struct come Contact, User, Item e assegnargli un nome specifico come chiave. E’ anche possibile estendere la logica di un videogioco e gestire i cambiamenti di stato del giocatore.

Per capire bene l’utilizzo di questi due tipi è importante conoscere le regole di ownership e di borrowing di Rust, che riguardano le regole di proprietà e di riferimento dei dati conservati in memoria.

Ritorniamo al progetto sulla lista dei contatti che abbiamo visto nell’articolo sui vettori in Rust e modifichiamo il type ContactList in HashMap<String,Contact>.

//Prima
pub(crate) type ContactList = Vec<Contact>;

//Dopo
pub(crate) type ContactList = HashMap<String,Contact>;

Modifichiamo il metodo per aggiungere nuovi contatti in modo da aggiungere sia la chiave che il valore della collezione.

//Prima
impl App {
    pub fn new(contact_list: ContactList) -> Self {
        Self { contact_list }
    }

    pub fn add(&mut self,new_contact:Contact) {
        let _ = &self.contact_list.push(new_contact);
    }
}

impl Console for App {
    fn show(&self) {
        for contact in &self.contact_list {
            contact.show();
        }
    }
}

//Dopo
impl App {
    pub fn new(contact_list: ContactList) -> Self {
        Self { contact_list }
    }

    pub fn add(&mut self,new_contact:Contact) {
        let _ = &self.contact_list.insert(new_contact.name().to_string(), new_contact);
    }
}

impl Console for App {
    fn show(&self) {
        for contact in &self.contact_list {
            println!("{}:", contact.0);
            contact.1.show();
        }
    }
}

Creiamo un metodo per ottenere il nome in String e modifichiamo il metodo show() per essere compatibile a quello dell’App.

impl Console for Contact {
    fn show(&self) {
        println!("  Nome: {:#?}",self.name);
        println!("  Numero: {:#?}",self.number);
    }
}

Modifichiamo il file main.rs in modo da usare le hash map invece dei vettori.

//Prima
use contact_list_example_rust::{app::App, contact::Contact, ui::Console};

fn main() {
    let mut app = App::new(Vec::new());

    app.add(Contact::new(String::from("Marco"), 33872564));

    app.show();
}

//Dopo
use std::collections::HashMap;

use contact_list_example_rust::{app::App, contact::Contact, ui::Console};

fn main() {
    let mut app = App::new(HashMap::new());

    app.add(Contact::new(String::from("Marco"), 33872564));

    app.show();
}

Puoi trovare tutto il codice nel branch del repository su Gt.