Collections: Vectors, Strings, and HashMaps
Learn to use common collection types like Vectors (resizable arrays), Strings (UTF-8 encoded text), and HashMaps (key-value pairs).
Rust HashMaps Explained
Collections: HashMaps
In Rust, like in many other programming languages, a HashMap
is a data structure that stores data in key-value pairs. It's a type of collection, which means it can hold multiple values. Unlike arrays or vectors where you access elements using an index (a number), you access elements in a HashMap
using a key.
The power of HashMaps lies in their efficiency for looking up values. Instead of searching through a list, the HashMap uses a special function called a hash function to calculate the location of a value based on its key. This allows for very fast retrieval of data, on average, much faster than linear search.
Understanding HashMaps and Key-Value Pairs in Rust
What are Key-Value Pairs?
A key-value pair is the fundamental building block of a HashMap. Think of it like a dictionary:
- Key: The "word" you're looking up. In a HashMap, keys must be unique within that HashMap.
- Value: The "definition" of the word. This is the data you want to store and retrieve.
For example, you might have a HashMap that stores student grades. The student's name could be the key, and their grade could be the value.
Creating a HashMap
To use a HashMap, you first need to bring it into scope using the use
keyword. Then, you can create a new, empty HashMap using HashMap::new()
. You also typically need to specify the types of the key and the value.
use std::collections::HashMap;
fn main() {
let mut student_grades: HashMap<&str, i32> = HashMap::new();
}
In this example:
use std::collections::HashMap;
imports the HashMap type.let mut student_grades: HashMap<&str, i32> = HashMap::new();
creates a mutable HashMap namedstudent_grades
.&str
is the type of the key (a string slice).i32
is the type of the value (a 32-bit integer).
Inserting Data into a HashMap
You can insert data into a HashMap using the insert()
method. It takes two arguments: the key and the value.
use std::collections::HashMap;
fn main() {
let mut student_grades: HashMap<&str, i32> = HashMap::new();
student_grades.insert("Alice", 90);
student_grades.insert("Bob", 85);
student_grades.insert("Charlie", 78);
}
This code inserts three key-value pairs:
"Alice"
(key) with90
(value)"Bob"
(key) with85
(value)"Charlie"
(key) with78
(value)
Retrieving Data from a HashMap
You can retrieve data from a HashMap using the get()
method. It takes the key as an argument and returns an Option<&V>
, where V
is the value type. The Option
type represents either Some(value)
if the key exists, or None
if the key does not exist.
use std::collections::HashMap;
fn main() {
let mut student_grades: HashMap<&str, i32> = HashMap::new();
student_grades.insert("Alice", 90);
student_grades.insert("Bob", 85);
let alice_grade = student_grades.get("Alice");
let david_grade = student_grades.get("David");
println!("Alice's grade: {:?}", alice_grade); // Output: Alice's grade: Some(90)
println!("David's grade: {:?}", david_grade); // Output: David's grade: None
// Safely access the value using match:
match student_grades.get("Alice") {
Some(grade) => println!("Alice's grade is: {}", grade),
None => println!("Alice's grade is not found"),
}
// Or using if let:
if let Some(grade) = student_grades.get("Bob") {
println!("Bob's grade is: {}", grade);
} else {
println!("Bob's grade is not found");
}
}
It's important to handle the Option
type to avoid errors if the key doesn't exist. The example demonstrates using match
and if let
for safe access.
Deleting Data from a HashMap
You can remove data from a HashMap using the remove()
method. It takes the key as an argument and returns an Option<V>
, where V
is the value type that was removed. The Option
type represents either Some(value)
if the key existed and was removed, or None
if the key did not exist.
use std::collections::HashMap;
fn main() {
let mut student_grades: HashMap<&str, i32> = HashMap::new();
student_grades.insert("Alice", 90);
student_grades.insert("Bob", 85);
let removed_grade = student_grades.remove("Alice");
println!("Removed Alice's grade: {:?}", removed_grade); // Output: Removed Alice's grade: Some(90)
let removed_grade_david = student_grades.remove("David");
println!("Removed David's grade: {:?}", removed_grade_david); // Output: Removed David's grade: None
println!("Student grades: {:?}", student_grades); // Output: Student grades: {"Bob": 85}
}
This code removes "Alice" from the HashMap. After the remove()
call, the HashMap only contains the key-value pair for "Bob".