Hash Maps
Using HashMap<K, V> to store key-value pairs.
Hash Maps
HashMap<K, V> stores key-value pairs, where each key is unique.
Creating a HashMap
RUSTuse std::collections::HashMap; let mut scores = HashMap::new(); scores.insert(String::from("Blue"), 10); scores.insert(String::from("Yellow"), 50);
Accessing Values
RUSTlet team_name = String::from("Blue"); let score = scores.get(&team_name); // Option<&V>
Iteration
RUSTfor (key, value) in &scores { println!("{}: {}", key, value); }
Updating Values
Overwriting
RUSTscores.insert(String::from("Blue"), 25); // Overwrites 10
Only if Key Doesn't Exist
RUSTscores.entry(String::from("Yellow")).or_insert(50);
Updating Based on Existing Value
RUSTlet 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; }
Ownership
RUSTlet field_name = String::from("Favorite color"); let field_value = String::from("Blue"); let mut map = HashMap::new(); map.insert(field_name, field_value); // field_name and field_value are no longer usable!
Code Examples
Basic HashMap
Creating and using a HashMap
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
println!("Scores: {:?}", scores);
}Explanation:
HashMap stores key-value pairs. The insert() method adds pairs. Keys must be unique.
Accessing Values
Accessing HashMap values
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
let team_name = String::from("Blue");
let score = scores.get(&team_name);
match score {
Some(value) => println!("Blue team score: {}", value),
None => println!("No such team"),
}
for (key, value) in &scores {
println!("{}: {}", key, value);
}
}Explanation:
The get() method returns Option<&V>. If the key exists, Some(value), if not, None. You can iterate with a for loop.
Entry API
Using Entry to update values
use std::collections::HashMap;
fn main() {
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;
}
println!("{:?}", map);
}Explanation:
The entry() API allows us to check if a key exists. or_insert() only adds a value if the key doesn't exist. Then we can modify the value.
Blockchain: Account Balances
Using HashMap for blockchain account balances
use std::collections::HashMap;
fn main() {
let mut balances: HashMap<String, u64> = HashMap::new();
balances.insert(String::from("0xAlice"), 1000);
balances.insert(String::from("0xBob"), 500);
balances.insert(String::from("0xCharlie"), 200);
if let Some(balance) = balances.get("0xAlice") {
println!("Alice's balance: {} tokens", balance);
}
if let Some(alice_balance) = balances.get_mut("0xAlice") {
*alice_balance -= 100;
}
if let Some(bob_balance) = balances.get_mut("0xBob") {
*bob_balance += 100;
}
println!("\nFinal balances:");
for (address, balance) in &balances {
println!("{}: {} tokens", address, balance);
}
}Explanation:
HashMaps are essential for blockchain state management. They map addresses to balances, allowing fast lookups and updates. This is how most blockchains store account state.
Blockchain: Transaction Nonces
Tracking transaction nonces with HashMap
use std::collections::HashMap;
fn main() {
let mut nonces: HashMap<String, u64> = HashMap::new();
nonces.insert(String::from("0xAlice"), 0);
nonces.insert(String::from("0xBob"), 0);
fn process_transaction(nonces: &mut HashMap<String, u64>, sender: &str) {
let current_nonce = nonces.entry(sender.to_string()).or_insert(0);
*current_nonce += 1;
println!("{} sent transaction with nonce {}", sender, current_nonce);
}
process_transaction(&mut nonces, "0xAlice");
process_transaction(&mut nonces, "0xAlice");
process_transaction(&mut nonces, "0xBob");
println!("\nFinal nonces:");
for (address, nonce) in &nonces {
println!("{}: {}", address, nonce);
}
}Explanation:
Nonces prevent replay attacks in blockchain. Each address has a nonce that increments with each transaction. HashMaps efficiently track nonces for all addresses.
Exercises
HashMap Practice
Create a HashMap, add some key-value pairs, and print all pairs!
Starter Code:
use std::collections::HashMap;
fn main() {
}Blockchain: Balance Tracker
Create a HashMap to track account balances!
Starter Code:
use std::collections::HashMap;
fn main() {
}