Day 3 · Concept 09
Vec, HashMap, String
Vec<T> = owned growable array. HashMap<K,V> = owned hash table.
String = owned UTF-8 string; &str = borrowed slice into one.
The split between owned and borrowed is the entire Rust collections API condensed.
1 · Vec — the workhorse
fn main() {
let mut v: Vec<i32> = Vec::new();
v.push(1);
v.push(2);
v.push(3);
// The macro is shorter
let v2 = vec![10, 20, 30];
// Index
println!("first: {}", v[0]);
// Iterate
for x in &v { println!("{}", x); }
// Map + collect
let doubled: Vec<i32> = v2.iter().map(|x| x * 2).collect();
println!("{:?}", doubled);
}2 · HashMap
use std::collections::HashMap;
fn main() {
let mut m: HashMap<&str, i32> = HashMap::new();
m.insert("alice", 30);
m.insert("bob", 25);
// Read with .get — returns Option<&V>
if let Some(age) = m.get("alice") {
println!("alice is {}", age);
}
// Or with the "entry" API to insert-if-absent
*m.entry("carol").or_insert(0) += 1;
*m.entry("carol").or_insert(0) += 1;
for (k, v) in &m {
println!("{}={}", k, v);
}
}3 · The big split: String vs &str
fn main() {
let owned: String = String::from("hello"); // owned, growable
let literal: &'static str = "world"; // borrowed (the binary owns it)
// Both are UTF-8.
// String can grow; &str cannot.
let mut owned = owned;
owned.push_str(", world");
println!("{}", owned);
// Pass &str when you only need to read — most common.
fn greet(s: &str) {
println!("hi, {}", s);
}
greet(&owned);
greet(literal);
greet("inline"); // string literal coerces
}The rule. Function parameters should be
&str when you only
read; String when you take ownership. String coerces to
&str via &, so the function works for both.4 · Other collections worth knowing
- VecDeque<T> — double-ended queue. push_back / pop_front in O(1).
- BTreeMap<K,V> — sorted map. Slower than HashMap but ordered.
- HashSet<T> / BTreeSet<T> — the set versions.
- LinkedList<T> — exists. Almost never the right choice. Use Vec.
- Box<T> — owned heap pointer. Smart pointer for "this exists, single-owned, heap".
5 · Common mistakes
- Indexing past the end. Vec[i] panics. Use
.get(i)for an Option. - Iterating and mutating. Can't hold a
&and a&mutsimultaneously. Collect indices first, then mutate. - Indexing strings.
s[0]doesn't compile — UTF-8 bytes aren't characters. Use.chars().nth(0)or.bytes().nth(0)depending. - Forgetting
use std::collections::HashMap;. It's not in the prelude.
6 · When it clicks
- You take
&strfor read;Stringfor own. By reflex. - The
.entry().or_insert()idiom replaces "check then insert" everywhere. - You reach for
iter().filter().map().collect()as a first choice over loops.
Found this useful?