Work with Collections

Need to work with collections in Rust? This guide covers vectors, hash maps, sets, and common collection operations with practical examples.

Problem: Creating and Using Vectors

Scenario

You need a growable array.

Solution: Use Vec

Create vectors:

// Empty vector
let mut v1: Vec<i32> = Vec::new();

// With initial capacity
let mut v2 = Vec::with_capacity(10);

// Using vec! macro
let v3 = vec![1, 2, 3, 4, 5];

// From iterator
let v4: Vec<i32> = (0..5).collect();

Add elements:

let mut v = Vec::new();
v.push(1);
v.push(2);
v.push(3);

Access elements:

let v = vec![1, 2, 3, 4, 5];

// Indexing (panics if out of bounds)
let third = v[2];

// Using get (returns Option)
match v.get(2) {
    Some(third) => println!("Third: {}", third),
    None => println!("No third element"),
}

Iterate:

let v = vec![1, 2, 3];

// Immutable iteration
for item in &v {
    println!("{}", item);
}

// Mutable iteration
for item in &mut v {
    *item += 1;
}

// Consuming iteration
for item in v {
    println!("{}", item);
}
// v is no longer valid

Problem: Working with Hash Maps

Scenario

You need key-value storage.

Solution: Use HashMap<K, V>

use std::collections::HashMap;

// Create hash map
let mut scores = HashMap::new();

// Insert values
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);

// Access values
let team = String::from("Blue");
let score = scores.get(&team).copied().unwrap_or(0);

// Iterate
for (key, value) in &scores {
    println!("{}: {}", key, value);
}

Update values:

let mut scores = HashMap::new();

// Overwrite value
scores.insert("Blue".to_string(), 10);
scores.insert("Blue".to_string(), 25);  // Now 25

// Only insert if key doesn't exist
scores.entry("Yellow".to_string()).or_insert(50);
scores.entry("Yellow".to_string()).or_insert(100);  // Still 50

// Update based on old value
let text = "hello world wonderful world";
let mut map = HashMap::new();

for word in text.split_whitespace() {
    let count = map.entry(word).or_insert(0);
    *count += 1;
}
// map: {"hello": 1, "world": 2, "wonderful": 1}

Create from iterator:

let teams = vec!["Blue", "Yellow"];
let initial_scores = vec![10, 50];

let scores: HashMap<_, _> = teams
    .iter()
    .zip(initial_scores.iter())
    .collect();

Problem: Using Sets for Unique Values

Scenario

You need to store unique values.

Solution: Use HashSet

use std::collections::HashSet;

let mut set = HashSet::new();

// Insert values (returns false if already exists)
set.insert(1);
set.insert(2);
set.insert(2);  // Duplicate, returns false

// Check existence
if set.contains(&1) {
    println!("Set contains 1");
}

// Remove
set.remove(&1);

// Iterate
for item in &set {
    println!("{}", item);
}

Set operations:

let a: HashSet<_> = vec![1, 2, 3, 4].into_iter().collect();
let b: HashSet<_> = vec![3, 4, 5, 6].into_iter().collect();

// Union
let union: HashSet<_> = a.union(&b).collect();
// {1, 2, 3, 4, 5, 6}

// Intersection
let intersection: HashSet<_> = a.intersection(&b).collect();
// {3, 4}

// Difference
let difference: HashSet<_> = a.difference(&b).collect();
// {1, 2}

// Symmetric difference
let sym_diff: HashSet<_> = a.symmetric_difference(&b).collect();
// {1, 2, 5, 6}

Problem: Maintaining Sorted Data

Scenario

You need collections that maintain sort order.

Solution: Use BTreeMap and BTreeSet

BTreeMap (sorted key-value pairs):

use std::collections::BTreeMap;

let mut map = BTreeMap::new();
map.insert(3, "c");
map.insert(1, "a");
map.insert(2, "b");

// Iterates in key order
for (key, value) in &map {
    println!("{}: {}", key, value);
}
// Output: 1: a, 2: b, 3: c

BTreeSet (sorted unique values):

use std::collections::BTreeSet;

let mut set = BTreeSet::new();
set.insert(3);
set.insert(1);
set.insert(2);

// Iterates in sorted order
for item in &set {
    println!("{}", item);
}
// Output: 1, 2, 3

Range queries:

use std::collections::BTreeMap;

let mut map = BTreeMap::new();
for i in 1..=10 {
    map.insert(i, i * 10);
}

// Get range
for (key, value) in map.range(3..=7) {
    println!("{}: {}", key, value);
}
// Output: 3: 30, 4: 40, 5: 50, 6: 60, 7: 70

Problem: Removing Duplicates from Vec

Scenario

You have a vector with duplicates to remove.

Solution 1: Use HashSet

use std::collections::HashSet;

let numbers = vec![1, 2, 2, 3, 4, 4, 5];
let unique: Vec<_> = numbers.into_iter().collect::<HashSet<_>>().into_iter().collect();
// Order not preserved

Solution 2: Preserve Order

use std::collections::HashSet;

let numbers = vec![1, 2, 2, 3, 4, 4, 5];
let mut seen = HashSet::new();
let unique: Vec<_> = numbers.into_iter()
    .filter(|x| seen.insert(*x))
    .collect();
// Order preserved: [1, 2, 3, 4, 5]

Solution 3: Sort and Dedup

let mut numbers = vec![1, 2, 2, 3, 4, 4, 5];
numbers.sort();
numbers.dedup();
// numbers: [1, 2, 3, 4, 5]

Problem: Transforming Collections

Scenario

You need to transform elements in a collection.

Solution: Use Iterator Methods

map - Transform each element:

let numbers = vec![1, 2, 3, 4, 5];
let squared: Vec<_> = numbers.iter()
    .map(|x| x * x)
    .collect();
// [1, 4, 9, 16, 25]

filter - Keep only matching elements:

let numbers = vec![1, 2, 3, 4, 5];
let evens: Vec<_> = numbers.iter()
    .filter(|x| *x % 2 == 0)
    .collect();
// [2, 4]

filter_map - Filter and transform:

let strings = vec!["1", "two", "3", "four", "5"];
let numbers: Vec<i32> = strings.iter()
    .filter_map(|s| s.parse().ok())
    .collect();
// [1, 3, 5]

fold - Reduce to single value:

let numbers = vec![1, 2, 3, 4, 5];
let sum = numbers.iter().fold(0, |acc, x| acc + x);
// 15

let product = numbers.iter().fold(1, |acc, x| acc * x);
// 120

Problem: Flattening Nested Collections

Scenario

You have nested collections to flatten.

Solution: Use flat_map or flatten

let nested = vec![vec![1, 2], vec![3, 4], vec![5, 6]];

// Using flatten
let flat: Vec<_> = nested.iter()
    .flatten()
    .collect();
// [1, 2, 3, 4, 5, 6]

// Using flat_map
let flat: Vec<_> = nested.iter()
    .flat_map(|v| v.iter())
    .collect();
// [1, 2, 3, 4, 5, 6]

With transformation:

let numbers = vec![1, 2, 3];
let repeated: Vec<_> = numbers.iter()
    .flat_map(|x| vec![*x, *x])
    .collect();
// [1, 1, 2, 2, 3, 3]

Problem: Grouping Elements

Scenario

You want to group elements by some criterion.

Solution: Use HashMap with entry API

use std::collections::HashMap;

let words = vec!["apple", "banana", "apricot", "blueberry", "cherry"];

let mut grouped: HashMap<char, Vec<&str>> = HashMap::new();

for word in words {
    let first_char = word.chars().next().unwrap();
    grouped.entry(first_char)
        .or_insert_with(Vec::new)
        .push(word);
}

// grouped: {'a': ["apple", "apricot"], 'b': ["banana", "blueberry"], 'c': ["cherry"]}

Problem: Finding Elements

Scenario

You need to find specific elements in a collection.

Solution: Use Iterator Methods

find - First matching element:

let numbers = vec![1, 2, 3, 4, 5];
let first_even = numbers.iter().find(|x| *x % 2 == 0);
// Some(2)

position - Index of first match:

let numbers = vec![1, 2, 3, 4, 5];
let pos = numbers.iter().position(|x| *x == 3);
// Some(2)

any - Check if any element matches:

let numbers = vec![1, 2, 3, 4, 5];
let has_even = numbers.iter().any(|x| x % 2 == 0);
// true

all - Check if all elements match:

let numbers = vec![2, 4, 6, 8];
let all_even = numbers.iter().all(|x| x % 2 == 0);
// true

Problem: Partitioning Collections

Scenario

You want to split a collection into two groups.

Solution: Use partition

let numbers = vec![1, 2, 3, 4, 5, 6];
let (evens, odds): (Vec<_>, Vec<_>) = numbers.into_iter()
    .partition(|x| x % 2 == 0);
// evens: [2, 4, 6], odds: [1, 3, 5]

Problem: Chunking Collections

Scenario

You need to process data in chunks.

Solution: Use chunks or windows

chunks - Non-overlapping chunks:

let numbers = vec![1, 2, 3, 4, 5, 6, 7];

for chunk in numbers.chunks(3) {
    println!("{:?}", chunk);
}
// [1, 2, 3]
// [4, 5, 6]
// [7]

windows - Sliding windows:

let numbers = vec![1, 2, 3, 4, 5];

for window in numbers.windows(3) {
    println!("{:?}", window);
}
// [1, 2, 3]
// [2, 3, 4]
// [3, 4, 5]

Problem: Combining Collections

Scenario

You need to combine multiple collections.

Solution: Use chain

let v1 = vec![1, 2, 3];
let v2 = vec![4, 5, 6];

let combined: Vec<_> = v1.iter()
    .chain(v2.iter())
    .collect();
// [1, 2, 3, 4, 5, 6]

Zip - Pair elements:

let names = vec!["Alice", "Bob", "Carol"];
let scores = vec![90, 85, 95];

let pairs: Vec<_> = names.iter()
    .zip(scores.iter())
    .collect();
// [("Alice", 90), ("Bob", 85), ("Carol", 95)]

Problem: Efficient String Collection

Scenario

You need to efficiently collect strings.

Solution: Use join

let words = vec!["Hello", "world", "from", "Rust"];

let sentence = words.join(" ");
// "Hello world from Rust"

let csv = words.join(",");
// "Hello,world,from,Rust"

Building strings from iterator:

let numbers = vec![1, 2, 3, 4, 5];
let text: String = numbers.iter()
    .map(|n| n.to_string())
    .collect::<Vec<_>>()
    .join(", ");
// "1, 2, 3, 4, 5"

Common Pitfalls

Pitfall 1: Unnecessary Clones

Problem: Cloning when borrowing would work.

// Bad
let v = vec![1, 2, 3];
let sum: i32 = v.clone().iter().sum();

// Good
let sum: i32 = v.iter().sum();

Pitfall 2: Not Using Iterators

Problem: Manual loops instead of iterator methods.

// Bad
let mut result = Vec::new();
for item in &vec {
    if item % 2 == 0 {
        result.push(item * 2);
    }
}

// Good
let result: Vec<_> = vec.iter()
    .filter(|x| *x % 2 == 0)
    .map(|x| x * 2)
    .collect();

Pitfall 3: HashMap with Non-Hash Types

Problem: Using types that don’t implement Hash.


---

## Related Resources

- [Tutorials: Beginner](/en/learn/software-engineering/programming-languages/rust/tutorials/beginner) - Collections fundamentals
- [Cookbook](/en/learn/software-engineering/programming-languages/rust/how-to/cookbook) - Collection recipes
- [Best Practices](/en/learn/software-engineering/programming-languages/rust/explanation/best-practices) - Idiomatic collection usage
- [Cheat Sheet](/en/learn/software-engineering/programming-languages/rust/reference/cheat-sheet) - Collection syntax reference

---

**Master Rust collections for effective data manipulation!**
Last updated