In Rust, how do I create a HashSet from the keys of a HashMap?

The simple solution

Your code only needs a few tweaks to actually compile (see Playground):

use std::collections::{HashSet, HashMap};

fn main() {
    let mut map1 = HashMap::new();
    let mut map2 = HashMap::new();

    // Add some values into the HashMaps for demonstration
    map1.insert(1, 10);
    map1.insert(5, 50);
    map2.insert(3, 30);
    map2.insert(5, 50);

    let set1: HashSet<i64> = map1.keys().cloned().collect();
    let set2: HashSet<i64> = map2.keys().cloned().collect();

    let set3 = set1.intersection(&set2);
    println!("{:?}", set3);
}

In particular, note map1.keys().cloned().collect():

  • HashMap<K, V>::keys() returns an Iterator<Item = &'a K>,
  • .cloned() transforms that to an Iterator<Item = K>,
  • .collect() builds a collection from that, since HashSet implements the FromIterator trait.

However, this is not very efficient:

  • Complexity wise: O(map1.size() + map2.size()).
  • Memory wise: potentially large allocations.

The efficient solution

Implement intersection directly on the keys of HashMap.


You just need to collect into the HashSet:

let set1: HashSet<i64> = map1.keys().copied().collect(); 
let set2: HashSet<i64> = map2.keys().copied().collect();

Using copied() will dereference the keys and copy them, since you want a HashSet<i64> not a HashSet<&i64>

Tags:

Rust