HashMap<&str,Foo> vs HashMap<String,Foo>


Hello all.

I have a struct which, among other things, owns a string called name. I have another struct which stores a hashmap of the previous struct. Something like:

struct Foo { name: String }
struct FooMgr { foos: HashMap<String, Foo> }

While this works, it involves additional cloning of Foo.name to act as a key in the hashmap.

What I really want is something like:

struct FooMgr { foos: HashMap<&str ,Foo> }

But I am stuck on how to deal with the lifetime for the &str in my add_foo method, since I want to associate it with Foo and not FooMgr. Can someone point me at an example or docs which would be relevant?


In short, what you’re attempting to do will create a self-referential struct.

To side step this, you can share the ownership of the string between the HashMap and the Foo:

struct Foo { name: Rc<str> }
struct FooMgr { foos: HashMap<Rc<str>, Foo> }

If you just want to look up the Foos by name, consider using a HashSet<Foo>, which you can query via HashSet::get. This method allows you to pass something that Foo can be borrowed as, so if you make it impl Borrow<str> for example, you can look them up by string slices.


Thanks vitalyd. I actually went down that road initially. Unfortunately, I hit an issue with my inability to call contains_key with a &str:
playground example


Yes, I remember this has bitten me as well, but as @vitalyd said, the trick is to use Rc<str>.

You can do it like this: https://play.rust-lang.org/?gist=f4e72644a290a6d8fa1dac00b65d3d2c&version=stable


Separately but relatedly, it seems like an omission that Rc<String> doesn’t impl Borrow<str>.


Vitalyd, birkenfeld, thank you both!