Rust Collections

What Are Collections in Rust?

Collections are data structures that store multiple values. Unlike fixed-size arrays, collections are dynamic and can grow or shrink as needed. Rust provides several commonly used collections:

  1. Vec<T> (Vector)
  2. String
  3. HashMap<K, V>
  4. HashSet<T>
  5. VecDeque<T>
  6. LinkedList<T>
  7. BinaryHeap<T>

Each collection is optimized for specific use cases, and selecting the right one is crucial for performance.

1. Vec<T>: The Vector

The vector is one of the most commonly used collections. It is a resizable array that stores elements of the same type.

Key Features

  • Stores elements in a contiguous memory block.
  • Allows indexing.
  • Can dynamically grow or shrink.

Example: Basic Vector Usage

fn main() {
let mut numbers: Vec<i32> = Vec::new(); // Create an empty vector
numbers.push(10); // Add elements
numbers.push(20);
numbers.push(30);

println!("{:?}", numbers); // Output: [10, 20, 30]

numbers.pop(); // Remove the last element
println!("{:?}", numbers); // Output: [10, 20]

for num in &numbers {
println!("{}", num); // Iterate over elements
}
}

2. String: Owned String Type

The String collection is used for dynamically growing, heap-allocated strings.

Key Features

  • Stores UTF-8 encoded text.
  • Can grow dynamically.
  • Provides extensive methods for string manipulation.

Example: String Operations

fn main() {
let mut greeting = String::from("Hello");
greeting.push_str(", world!"); // Append a string
println!("{}", greeting); // Output: Hello, world!

greeting.replace_range(0..5, "Hi"); // Replace part of the string
println!("{}", greeting); // Output: Hi, world!
}

3. HashMap<K, V>: Key-Value Store

The HashMap stores key-value pairs, where keys are unique.

Key Features

  • Provides fast lookup and insertion.
  • Keys must implement the Eq and Hash traits.

Example: Using HashMap

use std::collections::HashMap;

fn main() {
let mut scores = HashMap::new();
scores.insert("Alice", 50);
scores.insert("Bob", 40);

// Access a value
if let Some(score) = scores.get("Alice") {
println!("Alice's score: {}", score);
}

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

4. HashSet<T>: Unique Values

The HashSet ensures that all elements are unique.

Key Features

  • Does not allow duplicate values.
  • Provides set operations like union, intersection, and difference.

Example: Using HashSet

use std::collections::HashSet;

fn main() {
let mut fruits = HashSet::new();
fruits.insert("Apple");
fruits.insert("Banana");
fruits.insert("Apple"); // Duplicate, ignored

println!("{:?}", fruits); // Output: {"Apple", "Banana"}
}

5. VecDeque<T>: Double-Ended Queue

The VecDeque supports efficient addition and removal of elements from both ends.

Key Features

  • Useful for queues or deques.
  • More efficient than Vec for operations at both ends.

Example: Using VecDeque

use std::collections::VecDeque;

fn main() {
let mut deque = VecDeque::new();
deque.push_back(1);
deque.push_front(0);

println!("{:?}", deque); // Output: [0, 1]
}

6. LinkedList<T>: Doubly Linked List

The LinkedList provides sequential storage using nodes connected by pointers.

Key Features

  • Good for frequent insertions and deletions in the middle.
  • Slower for random access compared to Vec.

Example: Using LinkedList

use std::collections::LinkedList;

fn main() {
let mut list = LinkedList::new();
list.push_back(1);
list.push_front(0);

println!("{:?}", list); // Output: [0, 1]
}

7. BinaryHeap<T>: Priority Queue

The BinaryHeap is a max-heap by default, useful for implementing priority queues.

Key Features

  • Efficient for retrieving the maximum element.
  • Automatically maintains heap order.

Example: Using BinaryHeap

use std::collections::BinaryHeap;

fn main() {
let mut heap = BinaryHeap::new();
heap.push(4);
heap.push(7);
heap.push(1);

println!("{:?}", heap.pop()); // Output: Some(7) (max element)
}

Choosing the Right Collection

CollectionUse Case
Vec<T>When you need a dynamic, indexed list.
StringWhen you need a dynamically growable text.
HashMap<K, V>When you need a key-value store for fast lookup.
HashSet<T>When you need a collection of unique items.
VecDeque<T>When you need efficient additions/removals at both ends.
LinkedList<T>When frequent insertions/deletions in the middle are required.
BinaryHeap<T>When you need to maintain priority or retrieve the max/min element.

Leave a Comment

BoxofLearn