Ordered Collections

first_key_value() and last_key_value()

BTreeMap<K, V> provides .first_key_value(), .last_key_value(), .first_entry(), and .last_entry() (and BTreeSet<T> provides .first() and .last()) to inspect or mutate the minimum and maximum keys in the tree in $O(\log n)$ time without removing them.

Boundary Inspection and Entry Methods on BTreeMap<K, V>

Method Receiver Return Type Purpose
map.first_key_value() &self Option<(&K, &V)> Shared borrow of the smallest key and its value
map.last_key_value() &self Option<(&K, &V)> Shared borrow of the largest key and its value
map.first_entry() &mut self Option<OccupiedEntry<'_, K, V>> Mutable handle to the smallest key's entry (.get_mut(), .insert(), .remove())
map.last_entry() &mut self Option<OccupiedEntry<'_, K, V>> Mutable handle to the largest key's entry (.get_mut(), .insert(), .remove())

(On BTreeSet<T>, the corresponding read-only methods are set.first() -> Option<&T> and set.last() -> Option<&T>.)

Inspecting Minimum and Maximum Entries

use std::collections::BTreeMap;

fn main() {
    let latencies_ms = BTreeMap::from([
        (12_u32, "cache_hit"),
        (145, "db_query"),
        (4, "health_check"),
        (890, "cold_start"),
    ]);

    if let Some((min_ms, min_op)) = latencies_ms.first_key_value() {
        println!("Fastest operation: {min_op} ({min_ms} ms)");
    }

    if let Some((max_ms, max_op)) = latencies_ms.last_key_value() {
        println!("Slowest operation: {max_op} ({max_ms} ms)");
    }
}
Fastest operation: health_check (4 ms)
Slowest operation: cold_start (890 ms)

Mutating or Conditionally Removing the Minimum/Maximum via first_entry() and last_entry()

Notice that BTreeMap does not have a first_key_value_mut() method; instead, map.first_entry() and map.last_entry() return Option<OccupiedEntry<'_, K, V>>, which lets you both mutate the value in place (.get_mut()) or remove the boundary entry in $O(1)$ amortized node adjustment (.remove_entry()) without traversing the tree a second time:

use std::collections::BTreeMap;

fn main() {
    let mut order_book = BTreeMap::from([
        (100_u32, 5_u32), // price 100 -> 5 units
        (105, 12),        // price 105 -> 12 units
    ]);

    // Fill 3 units at the lowest ask price (`first_entry`):
    if let Some(mut lowest_ask) = order_book.first_entry() {
        *lowest_ask.get_mut() -= 3;
        println!(
            "Lowest ask @ {} now has {} units remaining",
            lowest_ask.key(),
            lowest_ask.get()
        );
    }

    // Cancel the highest ask price if its quantity is >= 10:
    if let Some(highest_ask) = order_book.last_entry() {
        if *highest_ask.get() >= 10 {
            let (price, qty) = highest_ask.remove_entry();
            println!("Canceled highest ask @ {price} ({qty} units)");
        }
    }

    println!("Order book: {order_book:?}");
}
Lowest ask @ 100 now has 2 units remaining
Canceled highest ask @ 105 (12 units)
Order book: {100: 2}