If I have a value, into_iter() collects values (and iter collects references):
let mut x = HashMap::new();
x.insert("1", 1);
x.insert("2", 2);
x.insert("3", 3);
let y: Vec<(&str, usize)> = x.into_iter().collect();
Whereas if we have a reference, we don't collect values, but references:
fn foo(x: &HashMap<&str, usize>) {
// This doesn't works
// let y: Vec<(&str, usize)> = x.into_iter().collect();
// This works
let y: Vec<(&&str, &usize)> = x.into_iter().collect();
}
Why? What surprised me even more is that all the types I am using are Copy (I was expecting that into_iter would either move the items from the container if the container was a value, or copy them if the container was a reference).
To make it possible to use a &HashMap directly as the thing to iterate over in a for loop, it must implement the IntoIterator trait, and this trait requires it (the reference type) to have an into_iter method. The iter method is just a convenience method defined on HashMap to disambiguate between into_iter on HashMap and the one on &HashMap.
What do you mean with "collect value"? You can't take ownership through an immutable reference, if that's what you're asking. You can clone it, though.
As always, it depends. You want to consume the map and collect its value? You can't since you only have a shared reference to the map. You want to drain the map and collect drained values? You can't drain the map with its shared reference. You want to iterate over references of the values and collect their copies? Sure you can, just map_ref.values().cloned().collect().
I want to have the same vec, that what I could get with this:
let map: HashMap<Foo, Bar> = /* ... */;
let vec: Vec<(Foo, Bar)> = map.into_iter().collect();
Obviously, if I have a &HashMap, I cannot consume its value, but if both Foo and Bar are copy, I should be able to to iterate over the map, copy each (key, value) pair, and then collect it in a Vec. This operation shouldn't need to allocate a new HashMap, just to be able to consume it.
What I want is semantically equivalent to this, but without the allocation of the unwarted_copyHashMap:
let ref_map: &HashMap<Foo, Bar> = /* ... */;
// this shouldn't be done since it will do work that isn't needed (dynamic allocation,
// 1 extra copy of everything, …)
let unwanted_copy = ref_map.clone();
// This is going to iterate and copy all pairs `(key, value)` from the map into a new vec.
// This works is needed and wanted.
let vec: Vec<(Foo, Bar)> = unwanted_copy.into_iter().collect();
// at that point, `vec` contains (in unspecified order) all `(key, value)` of `ref_map`
// and `ref_map` wasn't modified