Collections
The Rust standard library provides general-purpose, efficient data structures tailored for safe, high-performance memory management [562]. These collections are grouped into four major categories: Sequences, Maps, Sets, and Miscellaneous [562, 563, 564, 565].
Quick Selection Cheat Sheet
| Collection | Category | Memory Layout & Under the Hood | When to Use |
|---|---|---|---|
Vec<T> |
Sequence | Contiguous, dynamically resizable, heap-allocated array [562]. | The default go-to collection in Rust. Use when you need a sequence of elements with fast, indexed $O(1)$ dynamic lookups [562]. |
VecDeque<T> |
Sequence | Double-ended queue implemented as a growable ring buffer in memory [562]. | When you require efficient $O(1)$ insertion or removal of elements at both ends (front and back) [562]. |
LinkedList<T> |
Sequence | Doubly-linked list where each node is individually owned [562]. | Extremely rare in practice. Use only if you strictly need constant-time $O(1)$ splitting and appending without reallocating [562]. |
HashMap<K, V> |
Map | Hash table using linear probing and Robin Hood bucket stealing [563]. | For general key-value lookups, insertions, and removals in average $O(1)$ time [563]. Keys must implement Hash + Eq [563]. |
BTreeMap<K, V> |
Map | Self-balancing search tree based on a B-Tree structure [563]. | When you need keys stored in sorted order, need to query ranges of keys (via .range()), or require guaranteed $O(\log n)$ bounds [563]. |
HashSet<T> |
Set | Unordered set backed by a hash table [564] (light wrapper around HashMap<T, ()>) [564]. |
For fast deduplication and set membership checking in average $O(1)$ time [564]. Supports union, intersection, and difference [564]. |
BTreeSet<T> |
Set | Sorted set backed by a B-Tree [564] (light wrapper around BTreeMap<T, ()>) [564]. |
When you need a unique set of elements kept in sorted order or require range-based queries [564]. |
BinaryHeap<T> |
Miscellaneous | Priority queue implemented as a max-binary heap [565]. | When you need to retrieve the "greatest" element according to Ord in $O(\log n)$ time, while maintaining $O(1)$ peek access [565]. |
1. Sequences
Sequence collections store elements sequentially in dynamic memory [562].
Vec<T> (Vector)
The Vec is Rust's default array-like collection [562, 565]. It stores elements contiguously on the heap [562].
- Memory Footprint: On 64-bit systems, a
Vecheader occupies exactly 24 bytes on the stack [24, 25]. This is split across three 8-byte fields: a pointer to the heap buffer, capacity (usize), and length (usize) [25]. - The Cost of Dynamic Growth: When you initialize an empty vector using
Vec::new()and push elements onto it, it starts with zero capacity or a very small default [18, 19]. As elements exceed capacity:- Heap Reallocations: Rust requests a larger block of memory from the OS allocator, copies all existing items to the new address, and frees the old block [19].
- Checks: Every
.push()triggers a CPU check (len == capacity) to determine if a reallocation is required [19]. - Cache Invalidation: Moving data to a new memory address invalidates CPU cache lines [19].
- Optimization Best Practices:
- If the maximum size is known at compile-time and strictly capped, a stack-allocated fixed-size array (e.g.,
[u8; 100]) is the fastest option, as stack allocation takes virtually 0 CPU cycles and stays hot in L1/L2 caches [20, 22]. - If a heap-allocated vector is necessary, initialize it with
Vec::with_capacity(capacity)to pre-allocate memory [21, 23]. This eliminates intermediate reallocations and turns pushes into simple pointer increments [21].
- If the maximum size is known at compile-time and strictly capped, a stack-allocated fixed-size array (e.g.,
VecDeque<T> (Double-Ended Queue)
A VecDeque uses a growable ring buffer [562]. It is ideal for FIFO (First-In, First-Out) or double-ended queues [565].
- Performance: It offers $O(1)$ push and pop operations at both the front and back of the sequence [562].
- Contrast with
Vec: WhileVecis optimized for push and pop at the end, pushing to the front of aVecis an $O(n)$ operation because all downstream elements must be shifted in memory.
LinkedList<T> (Doubly-Linked List)
A doubly-linked list where each node has owned allocations [562].
- The Cache Locality Penalty:
LinkedListis rarely used in systems programming [562]. Because nodes are scattered across the heap rather than stored contiguously like aVecorVecDeque, they suffer from poor CPU cache locality [562]. - Appropriate Use Cases: Use only when you have large datasets where you must perform constant-time $O(1)$ list splitting and appending operations without triggering memory reallocations [562].
2. Maps
Maps store unique keys associated with values [563].
HashMap<K, V>
The HashMap is Rust's default key-value collection [565]. It uses a hash table layout implemented with linear probing and Robin Hood bucket stealing [563].
- Performance: On average, it provides $O(1)$ time complexity for lookups, insertions, and removals [563].
- Requirements: The key type
Kmust implement theHashandEqtraits [563]. - Contrast with Sequence Lookups: Using a vector for key lookups forces $O(n)$ linear searches [30]. For example, managing active background jobs or data registries by ID using a
HashMapis vastly superior to iterating over a dynamic vector because it permits direct, constant-time $O(1)$ retrieval [30].
BTreeMap<K, V>
A map based on a self-balancing B-Tree structure [563].
- Guaranteed Bounds: While
HashMaphas average $O(1)$ performance, a bad hashing function can degrade performance.BTreeMapprovides strict $O(\log n)$ performance bounds regardless of hashing quality [563]. - Sorted Order: Keys are maintained in sorted order according to their
Ordimplementation [563]. - Range Queries: It provides powerful range-based lookups using the
.range()method (e.g., retrieving all entries within a specific key boundary) [563].
3. Sets
Sets store unique individual keys without associated values [564].
- Under the Hood: Standard library sets are lightweight wrappers around their corresponding Map implementations [564]:
HashSet<T>is a wrapper aroundHashMap<T, ()>[564].BTreeSet<T>is a wrapper aroundBTreeMap<T, ()>[564].
HashSet<T>: Offers unordered storage with average $O(1)$ deduplication and membership checks [564]. It supports standard mathematical set operations such as union, intersection, and difference [564].BTreeSet<T>: Maintains its elements in sorted order based on the B-Tree structure, making it ideal for range queries on unique elements [564].
4. Miscellaneous
BinaryHeap<T>
A priority queue implemented as a max-binary heap [565].
- Ordering: The queue always prioritizes the "greatest" element based on the
Ordtrait implementation of the elements [565]. - Complexity:
- Popping the greatest element takes $O(\log n)$ time [565].
- Peeking at the maximum element without removing it is a constant-time $O(1)$ operation [565].