Ordered Collections

BTreeMap

BTreeMap<K, V> (std::collections::BTreeMap) is a self-balancing ordered associative map backed by a multi-element B-Tree ($B = 6$) that keeps its keys sorted in ascending K: Ord order and guarantees $O(\log n)$ worst-case lookup, insertion, removal, and boundary queries.

Internal B-Tree Node Architecture ($B = 6$)

Unlike a binary search tree (which allocates one node per key and chases pointers at every binary step), Rust's BTreeMap uses a branching factor of $B = 6$:

  • Every non-root node contains between $B - 1 = 5$ and $2B - 1 = 11$ sorted keys (and values) stored in contiguous inline arrays.
  • Internal (non-leaf) nodes also store between $B = 6$ and $2B = 12$ child node pointers (edges).
                Internal Node (up to 11 keys, 12 child pointers)
                +---------------------------------------------+
                | keys: [     20     |     50     | ... ]     |
                | vals: [     v20    |     v50    | ... ]     |
                +---------+----------+----------+-------------+
                          |                     |                     \
                          v                     v                      v
        Leaf Node (< 20)             Leaf Node (20..50)             Leaf Node (> 50)
   +-----------------------+    +------------------------+    +------------------------+
   | keys: [ 5, 10, 15 ]   |    | keys: [ 25, 30, 40 ]   |    | keys: [ 60, 75, 90 ]   |
   | vals: [ v5, v10, v15 ]|    | vals: [ v25, v30, v40 ]|    | vals: [ v60, v75, v90 ]|
   +-----------------------+    +------------------------+    +------------------------+

Because each internal node branches up to 12 ways, a BTreeMap holding 1,000,000 entries has a tree height of at most 5 to 6 levels, and searching within a single node scans a tiny contiguous array inside 1–2 CPU cache lines.

Constructing and Querying a BTreeMap<K, V>

BTreeMap::new() is a const fn that performs zero heap allocation until the first key-value pair is inserted. Unlike HashMap, BTreeMap has no with_capacity or reserve method because B-Tree nodes are allocated incrementally as keys are inserted and split:

use std::collections::BTreeMap;

static EMPTY_MAP: BTreeMap<u32, &str> = BTreeMap::new();

fn main() {
    let mut routing_table = BTreeMap::from([
        (30, "gateway-c"),
        (10, "gateway-a"),
        (20, "gateway-b"),
    ]);

    routing_table.insert(15, "gateway-a-backup");

    // Iteration is guaranteed to visit keys in ascending `Ord` order (10, 15, 20, 30):
    for (metric, gateway) in &routing_table {
        println!("metric {metric:>2} -> {gateway}");
    }
    println!("Static empty len: {}", EMPTY_MAP.len());
}
metric 10 -> gateway-a
metric 15 -> gateway-a-backup
metric 20 -> gateway-b
metric 30 -> gateway-c
Static empty len: 0