Advanced Collections: HashSet and BTreeMap in Rust

Rust provides powerful built-in collections like HashSet and BTreeMap for managing unique items and sorted key-value pairs. These types are part of the std::collections module and are commonly used in real-world Rust applications where performance, uniqueness, and order matter.

After learning the basic collections like Vec and HashMap, I wanted to explore more specialized tools. That is when I discovered HashSet and BTreeMap. These collections solve different problems: HashSet is perfect when you need uniqueness, and BTreeMap is ideal when you need keys in sorted order. Understanding when and how to use them gave me more confidence in choosing the right data structure for each job.

In this post, you will learn what these collections are, how to use them, and when to prefer one over the other.

What Is a HashSet?

A HashSet is a collection of unique values. It is like a Vec, but it automatically rejects duplicates.

It is useful when:

  • You want to check if a value exists quickly
  • You want to collect unique items from a list
  • You do not care about order

You need to import it from the standard collections module:

use std::collections::HashSet;

Creating and Using a HashSet

Here is a basic example:

let mut colors = HashSet::new();

colors.insert("red");
colors.insert("blue");
colors.insert("red"); // duplicate, will be ignored

println!("{:?}", colors); // {"blue", "red"}

To check for a value:

if colors.contains("red") {
    println!("It is in the set.");
}

To remove an item:

colors.remove("red");

Useful Methods for HashSet

  • len(): count of items
  • is_empty(): check if it is empty
  • clear(): remove all items
  • iter(): loop through all items
  • retain(): keep items that match a condition

HashSet does not preserve insertion order. If you need order, consider a BTreeSet.

Set Operations

HashSet supports common set operations:

let a: HashSet<_> = [1, 2, 3].into_iter().collect();
let b: HashSet<_> = [3, 4, 5].into_iter().collect();

let union: HashSet<_> = a.union(&b).copied().collect();      // {1, 2, 3, 4, 5}
let intersect: HashSet<_> = a.intersection(&b).copied().collect(); // {3}
let diff: HashSet<_> = a.difference(&b).copied().collect();  // {1, 2}

These are great for comparing user permissions, tags, and categories.

What Is a BTreeMap?

A BTreeMap is a sorted key-value map, like HashMap, but it stores keys in order.

It is useful when:

  • You want to iterate keys in sorted order
  • You want predictable iteration
  • You do not need the speed of a hash map

Import it from the standard library:

use std::collections::BTreeMap;

Creating and Using a BTreeMap

Example:

let mut scores = BTreeMap::new();

scores.insert("Alice", 50);
scores.insert("Bob", 60);
scores.insert("Charlie", 40);

for (name, score) in &scores {
    println!("{}: {}", name, score);
}

Output:

Alice: 50
Bob: 60
Charlie: 40

The keys are printed in sorted order automatically.

Access and Modify

  • get(key) – returns an Option with the value
  • insert(key, value) – inserts or updates a key
  • remove(key) – removes a key
if let Some(score) = scores.get("Alice") {
    println!("Alice scored {}", score);
}

Comparing HashMap vs BTreeMap

FeatureHashMapBTreeMap
Key OrderNoYes (sorted by key)
PerformanceFastest for random accessSlower but predictable
Memory UsageHigherMore efficient
Key RequirementsNeeds Hash + Eq traitsNeeds Ord + Eq traits

Use HashMap for performance. Use BTreeMap when you need order.

Example: Counting Unique Words

Here is a practical use of HashSet:

let sentence = "the quick brown fox jumps over the lazy dog";
let words: HashSet<_> = sentence.split_whitespace().collect();

println!("Unique words: {}", words.len()); // 8

Here is an example with BTreeMap:

let sentence = "hello world hello rust";
let mut counts = BTreeMap::new();

for word in sentence.split_whitespace() {
    *counts.entry(word).or_insert(0) += 1;
}

for (word, count) in &counts {
    println!("{}: {}", word, count);
}

This prints the words in sorted order with their counts.

Summary

Rust’s HashSet and BTreeMap give you powerful tools for working with unique data and sorted key-value pairs. Use HashSet when you want fast, unordered lookups. Use BTreeMap when you want predictable order with sorted keys. These collections are easy to use, memory-efficient, and part of Rust’s safe and expressive ecosystem.