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}