Printing hashmaps

Code

use std::collections::HashMap;

let mut scores = HashMap::new();

scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);

for (key, value) in &scores {
    println!("{}: {}", key, value);
}

Output

Yellow: 50
Blue: 10

How come the yellow: 50 gets printed out first? Shouldn't it be Blue: 10 that gets printed out first cause we added this first?

And also in this line of code

for (key, value) in &scores {
    println!("{}: {}", key, value);
}

How come we are using &scores instead of scores?

3 Likes

HashMap does not keep keys in order of insertion.
From docs:

pub fn iter(&self) -> Iter<K, V>
An iterator visiting all key-value pairs in arbitrary order.

You will have to track it by yourself or use some crate, which implements it for you, for example linked-hash-map .

1 Like

Another option is indexmap, which maintains insertion order and lets you retrieve items by usize index, in addition to normal hashed key lookups.

3 Likes

You could use either. The difference is that if you use scores, you will consume the HashMap and you will not be able to use it later. When using &scores, you can use the HashMap later, but the types of key and value will be references.

1 Like

Some additional context as to why it works this way - for loops are built on top of the IntoIterator trait. Whatever you pass after the in keyword will implicitly have IntoIterator::into_iter called on it. So let's find the relevant implementations for your case!

  • The type of scores is HashMap, so impl IntoIterator for HashMap is used - this returns an iterator of values, so it must consume the HashMap.
  • The type of &scores is &Hashmap, so impl IntoIterator for &HashMap is used - this returns an iterator of references, so it doesn't consume the original HashMap.

There's more good info on this behavior in the std::iter docs.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.