Ordered Collections

range_mut()

The .range_mut(range) method on BTreeMap<K, V> returns a double-ended iterator (std::collections::btree_map::RangeMut<'_, K, V>) that yields (&K, &mut V) pairs for all keys within the specified range, allowing in-place mutation of values across a key subrange in $O(\log n + k)$ time.

Signature and Key Immutability

pub fn range_mut<T, R>(&mut self, range: R) -> RangeMut<'_, K, V>
where
    T: Ord + ?Sized,
    K: Borrow<T> + Ord,
    R: RangeBounds<T>,

Just like .iter_mut(), .range_mut() yields a shared reference to the key (&K) and an exclusive mutable reference to the value (&mut V):

  • Mutating *val in place is completely safe and never rebalances the tree.
  • Keys cannot be mutated in place because changing a key's sort order would violate the B-Tree invariant. (For BTreeSet<T>, there is no range_mut method because set elements are the keys.)

Updating Values Across a Time or Key Window with range_mut()

use std::collections::BTreeMap;

fn main() {
    let mut prices_by_tier = BTreeMap::from([
        (1_u8, 100_u32),
        (2, 200),
        (3, 300),
        (4, 400),
        (5, 500),
    ]);

    // Apply a +50 surcharge only to mid-level tiers `2..=4`:
    for (_tier, price) in prices_by_tier.range_mut(2..=4) {
        *price += 50;
    }

    println!("Updated tiers: {prices_by_tier:?}");
}
Updated tiers: {1: 100, 2: 250, 3: 350, 4: 450, 5: 500}

Modifying Only the First or Last Matching Element in a Range

Because RangeMut implements DoubleEndedIterator, calling .next() or .next_back() on map.range_mut(...) lets you mutate the value of the ceiling ($\ge x$) or floor ($\le x$) key in $O(\log n)$ time:

use std::collections::BTreeMap;

fn main() {
    let mut buckets = BTreeMap::from([
        (10_u32, vec!["small"]),
        (50, vec!["medium"]),
        (100, vec!["large"]),
    ]);

    let item_size = 35_u32;

    // Find the smallest bucket with capacity >= `item_size` (50) and push to its Vec:
    if let Some((&bucket_cap, items)) = buckets.range_mut(item_size..).next() {
        items.push("new_item_35");
        println!("Placed item of size {item_size} into bucket {bucket_cap}: {items:?}");
    }
}
Placed item of size 35 into bucket 50: ["medium", "new_item_35"]