Come cercare e inserire in una HashMap in modo efficiente?

Mi piacerebbe fare quanto segue:

  • Cerca un Vec per un determinato tasto e memorizzalo per un uso futuro.
  • Se non esiste, crea un Vec vuoto per la chiave, ma conservalo nella variabile.

Come farlo in modo efficiente? Naturalmente pensavo di poter usare la match :

 use std::collections::HashMap; // This code doesn't compile. let mut map = HashMap::new(); let key = "foo"; let values: &Vec = match map.get(key) { Some(v) => v, None => { let default: Vec = Vec::new(); map.insert(key, default); &default } }; 

Quando ho provato, mi ha dato errori come:

 error[E0502]: cannot borrow `map` as mutable because it is also borrowed as immutable --> src/main.rs:11:13 | 7 | let values: &Vec = match map.get(key) { | --- immutable borrow occurs here ... 11 | map.insert(key, default); | ^^^ mutable borrow occurs here ... 15 | } | - immutable borrow ends here 

Ho finito per fare qualcosa del genere, ma non mi piace il fatto che esegua la ricerca due volte ( map.contains_key e map.get ):

 // This code does compile. let mut map = HashMap::new(); let key = "foo"; if !map.contains_key(key) { let default: Vec = Vec::new(); map.insert(key, default); } let values: &Vec = match map.get(key) { Some(v) => v, None => { panic!("impossiburu!"); } }; 

C’è un modo sicuro per farlo con una sola match ?

    L’ API entry è progettata per questo. In forma manuale, potrebbe sembrare

     use std::collections::hash_map::Entry; let values: &Vec = match map.entry(key) { Entry::Occupied(o) => o.into_mut(), Entry::Vacant(v) => v.insert(default) }; 

    Oppure si può usare il modulo più breve:

     map.entry(key).or_insert_with(|| default) 

    Se il default è OK / economico da calcolare anche quando non è inserito, può anche essere solo:

     map.entry(key).or_insert(default)