HashMap borrow issue when trying to implement find or insert

后端 未结 2 473
时光取名叫无心
时光取名叫无心 2020-12-07 04:00

I tried to implement own analogue of find_or_insert method that looks like this:

use std::collections::HashMap;

pub struct SomeManager {
    ne         


        
相关标签:
2条回答
  • 2020-12-07 04:45

    Note that in your first case you're doing one lookup when the key exists in the map and three when it does not exist. Your last attempt does two lookups in either case. This is somewhat prettified version of the latter:

    pub fn get_type<'a>(&'a mut self, k: i32) -> &'a i32 {
        let contains = self.types.contains_key(&k);
        if !contains {
            self.types.insert(k, self.next);
            self.next += 1;
        }
        self.types.get(&k).unwrap()
    }
    

    I don't think it is possible to avoid the second lookup without some support from the map's implementation because of borrowing restrictions.

    In any case, using the solution by Chris Morgan is superior to the above one (for example, it may be more efficient and in fact require less lookups), so I suggest sticking with it.

    0 讨论(0)
  • 2020-12-07 04:57

    There are a handful of methods on HashMap to achieve these sorts of complex cases. Most notably, for your case, HashMap::entry and Entry::or_insert_with:

    pub fn get_type<'a>(&'a mut self, k: i32) -> &'a i32 {
        self.types.entry(k).or_insert_with(|| {
            let value = self.next;
            self.next += 1;
            value
        })
    }
    

    In your case, however, there’s the borrow of self inside, so that won’t do.

    We thus shift the borrow of self.next outside of the closure so the compiler can reason about it as disjoint from self.types. Problem solved with only one lookup, as it should be.

    pub fn get_type<'a>(&'a mut self, k: i32) -> &'a i32 {
        let next = &mut self.next;
    
        self.types.entry(k).or_insert_with(|| {
            let value = *next;
            *next += 1;
            value
        })
    }
    
    0 讨论(0)
提交回复
热议问题