Collections: The "Dynamic Containers"
In JavaScript, every Array or Object is dynamic. You can add or remove elements whenever you want. In Rust, we use Collections when we need that same flexibility.
Think of Collections as Dynamic Toolboxes. While Primitives like arrays have a fixed size, Collections grow and shrink as your application needs more space, and they are always stored on the Heap.
🏗️ The 3-Step Narrative
1. Vec<T>: The “Growable List”
A Vector is essentially a JS Array. It stores a list of values of the same type right next to each other in memory.
- What it unlocks: The ability to push, pop, and iterate over items without knowing the final count at compile-time.
let mut v = Vec::new(); // 📦 Creating an empty vectorv.push(1); // 🪄 Adding itemsv.push(2);
let v2 = vec![1, 2, 3]; // ✨ Using the macro for instant creation2. HashMap<K, V>: The “Dictionary”
A HashMap is like a JS Object or a Map. It stores key-value pairs where every key is unique.
- What it unlocks: Quick lookup of data based on a key (e.g., finding a “User” by their “ID”).
use std::collections::HashMap;
let mut scores = HashMap::new();scores.insert(String::from("Blue"), 10); // 🏷️ Inserting a recordscores.insert(String::from("Yellow"), 50);3. The Entry Contract
Rust’s HashMap has a unique “Entry API” that makes updating data feel like a clean contract.
let mut counts = HashMap::new();let text = "hello world";
for word in text.split_whitespace() { // 🪄 "or_insert" only inserts if the key doesn't exist let count = counts.entry(word).or_insert(0); *count += 1;}🔬 From the Official Book
⚡ Iterating Over Collections
You spend most of your time iterating. Use .iter() to borrow the data, or .into_iter() to take ownership of it.
let v = vec![100, 32, 57];for i in &v { println!("{i}"); // 🔍 Borrowing}💡 What Collections Unlock
- Real-World Data: You can’t always know how many items a user will input.
VecandHashMapallow your application to scale with its data. - Efficient Filtering: Combined with Iterators and Closures, you can transform your collections with the same speed as a manual
forloop. - Safety by Default: Rust ensures that you never “go out of bounds” in a way that crashes your program—it will return an
Option::Noneinstead!