Learning Rust Part 5 - Data Structures
30 Oct 2024Introduction
Rust offers a versatile range of data structures that make working with various types of data efficient and safe. In this post, we’ll cover fundamental data structures like vectors, hash maps, and arrays, along with Rust’s powerful enums and structs for creating custom data types.
Text
Strings and String Slices
Rust provides two main string types:
- String: A growable, heap-allocated string.
- &str (string slice): An immutable view into a string, commonly used for read-only access.
String example:
String slice example:
Collections
Vectors
Vectors (Vec<T>
) are dynamic arrays that can grow or shrink in size, making them ideal for storing sequences of values
when the size isn’t known at compile-time.
LinkedList
A LinkedList<T>
is a doubly linked list that allows fast insertion and deletion of elements at both ends of the list.
It is less commonly used than Vec
but can be useful when you need to insert and remove elements frequently from both
the front and back of the collection.
HashMap
A HashMap<K, V>
stores key-value pairs, enabling efficient value retrieval based on keys.
BTreeMap
BTreeMap<K, V>
is similar to HashMap
but keeps keys sorted, making it useful for scenarios where sorted keys are
necessary.
BinaryHeap
A BinaryHeap<T>
is a priority queue implemented with a binary heap, where elements are always ordered so the largest
(or smallest) element can be accessed quickly. By default, BinaryHeap
maintains a max-heap, but it can be customized
for min-heap operations.
HashSet
A HashSet<T>
is a collection of unique values, implemented as a hash table. It provides fast membership checking and
is useful when you need to store non-duplicate items without any specific order.
BTreeSet
A BTreeSet<T>
is a sorted, balanced binary tree-based set. Like HashSet
, it only stores unique values, but unlike
HashSet
, it maintains its items in sorted order. This makes it suitable for range queries and ordered data.
VecDeque
A VecDeque<T>
(double-ended queue) is a resizable, efficient data structure that supports adding and removing elements
from both the front and back. It’s ideal for queue-like operations where both ends need to be accessible.
Option
and Result
Types
Rust’s Option
and Result
types are enums that enable safe handling of optional values and errors. We went over
error handling in part 3 of this series.
Option
The Option<T>
type represents an optional value: Some(T)
for a value, or None
if absent.
Result
The Result<T, E>
type is used for functions that may succeed (Ok(T)
) or fail (Err(E)
), promoting explicit error
handling.
Custom Data Types and Enums
Rust’s enums and structs allow you to create custom data types, essential for building complex and expressive programs.
Enums
Rust’s enums can hold different types of data within each variant, enabling versatile data representations.
Structs and Tuple Structs
Structs allow for creating complex types with named fields.
Tuple structs are useful for grouping values without naming fields, often for simpler data types.
Arrays, Slices, and Compile-Time Length Arrays
Arrays
Arrays in Rust are fixed-size collections of elements with known length at compile-time. They’re stack-allocated, offering efficiency and safety.
Slices
Slices provide a way to view sections of an array or vector, avoiding the need to copy data.
Slices work with both arrays and vectors and are typically used as function parameters to avoid copying large data structures.
Reference Counting
Rc<Vec<T>>
and Arc<Vec<T>>
Rc
(Reference Counting) and Arc
(Atomic Reference Counting) are common wrappers around collections like Vec
to
allow multiple ownership. Rc
is single-threaded, while Arc
is thread-safe, and both are used frequently for sharing
collections between parts of a program.
Summary
Rust’s data structures—from collections like Vec
and HashMap
to custom types with struct
and enum
—enable
flexible, efficient, and safe data handling. With tools like Option
and Result
, Rust enforces a safety-first
approach without compromising on performance, making it an ideal language for robust application development.