diff --git a/content/rust/concepts/collections/collections.md b/content/rust/concepts/collections/collections.md index 0fd17177bbc..a93c0e5d020 100644 --- a/content/rust/concepts/collections/collections.md +++ b/content/rust/concepts/collections/collections.md @@ -11,4 +11,176 @@ CatalogContent: - 'paths/computer-science' --- -In Rust, **collections** are fundamental data structures offered by the standard library, enabling the storage and manipulation of multiple values. These dynamic structures differ from fixed-size `arrays` and `tuples` by allowing a variable number of elements. The key advantage lies in their ability to dynamically allocate memory on the heap, which means that the amount of data does not need to be known at compile time and can shrink and grow during runtime. The most commonly used collection data types include `vector`, `string`, and `Hashmap`. The rest include `VecDeque`, `LinkedList`, `BTreeMap`, `set`, and `BinaryHeap`. +In Rust, **collections** are standard library data structures that let you store and work with multiple values. Unlike fixed-size `arrays` and `tuples`, collections can grow and shrink at runtime because they allocate on the heap. Commonly used collections include `Vec`, `String`, and `HashMap`. Others include `VecDeque`, `LinkedList`, `BTreeMap`, `BinaryHeap`, and set types. + +--- + +## Vector (`Vec`) + +```rust +fn main() { + let mut nums = Vec::new(); + nums.push(10); + nums.push(20); + nums.push(30); + + for n in &nums { + println!("{n}"); + } +} +```` + +--- + +## String + +```rust +fn main() { + let mut s = String::from("Hi"); + s.push_str(", Rust!"); + println!("{s}"); +} +``` + +--- + +## HashMap + +```rust +use std::collections::HashMap; + +fn main() { + let mut scores = HashMap::new(); + scores.insert("alice", 12); + scores.insert("bob", 18); + + if let Some(v) = scores.get("alice") { + println!("Alice has {v}"); + } +} +``` + +--- + +## VecDeque + +```rust +use std::collections::VecDeque; + +fn main() { + let mut q = VecDeque::new(); + q.push_back("task1"); + q.push_back("task2"); + q.push_front("urgent"); + + while let Some(job) = q.pop_front() { + println!("{job}"); + } +} +``` + +--- + +## LinkedList + +```rust +use std::collections::LinkedList; + +fn main() { + let mut list = LinkedList::new(); + list.push_back("a"); + list.push_back("b"); + list.push_front("start"); + + for v in list { + println!("{v}"); + } +} +``` + +--- + +## BTreeMap + +```rust +use std::collections::BTreeMap; + +fn main() { + let mut map = BTreeMap::new(); + map.insert(3, "three"); + map.insert(1, "one"); + map.insert(2, "two"); + + for (k, v) in &map { + println!("{k} -> {v}"); + } +} +``` + +--- + +## BinaryHeap + +```rust +use std::collections::BinaryHeap; + +fn main() { + let mut heap = BinaryHeap::new(); + heap.push(10); + heap.push(4); + heap.push(7); + + while let Some(max) = heap.pop() { + println!("{max}"); // prints in descending order + } +} +``` + +--- + +## HashSet (example set type) + +```rust +use std::collections::HashSet; + +fn main() { + let mut set = HashSet::new(); + set.insert("apple"); + set.insert("banana"); + set.insert("apple"); // duplicate ignored + + for item in set { + println!("{item}"); + } +} +``` + +--- + +## When to use which collection + +| Collection | Use it when | Notes and tradeoffs | +| ---------------- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Vec` | You need an ordered, indexable, growable list and will mostly push and iterate. | Appends at the end are fast. Inserting or removing in the middle shifts elements. Best default when you just need a list. | +| `String` | You need owned, growable UTF-8 text. | Indexing by position is not constant time because of UTF-8. Use `push_str`, `push`, and slicing by ranges found from methods like `char_indices`. | +| `HashMap` | You need to associate keys with values with average constant-time lookups. | Order is not stable. Requires `Hash` for keys. Good general map when you do not care about key order. | +| `VecDeque` | You need a queue where you push and pop at both ends efficiently. | Provides amortized constant-time `push_front` and `push_back`. Indexed access exists but the layout is a ring buffer. | +| `LinkedList` | You will do many insertions and removals in the middle using list nodes that you already have. | Rarely faster than `Vec`. Consider it only for special cases where node ownership matters more than cache locality. | +| `BTreeMap` | You need a map that iterates in key order or you need range queries. | Slower lookups than `HashMap` but order is guaranteed and range operations are efficient. | +| `BinaryHeap` | You need to repeatedly pop the largest (or smallest with `Reverse`) element. | Great for priority queues and scheduling. Not for random indexed access. | +| `HashSet` | You need to track membership or remove duplicates with average constant-time checks. | Order is not stable. If you need sorted iteration, use `BTreeSet`. | + +--- + +## One-line use cases + +* `Vec`: grow a list of items then iterate in order. +* `String`: build user-visible text that changes over time. +* `HashMap`: cache or count things by key with fast lookups. +* `VecDeque`: implement a FIFO queue or sliding window. +* `LinkedList`: splice or move existing nodes without copying elements. +* `BTreeMap`: keep data sorted by key and run range queries. +* `BinaryHeap`: always get the next highest-priority item first. +* `HashSet`: track unique items and test membership quickly. + +