Альтернативні/користувацькі типи ключів
Будь-який тип, що реалізує трейти Eq і Hash, може бути ключем у HashMap.
Це включає:
bool(хоча не дуже корисно, оскільки існує лише два можливі ключі)int,uint, і всі їхні варіаціїStringі&str(protip: ви можете матиHashMapз ключемStringі викликати.get()з&str)
Зверніть увагу, що f32 і f64 не реалізують Hash,
ймовірно, тому що помилки точності чисел з плаваючою комою
робили б використання їх як ключів hashmap жахливо схильним до помилок.
Усі класи колекцій реалізують Eq і Hash,
якщо їхній тип, що міститься, також відповідно реалізує Eq і Hash.
Наприклад, Vec<T> реалізує Hash, якщо T реалізує Hash.
Ви можете легко реалізувати Eq і Hash для користувацького типу лише одним рядком:
#[derive(PartialEq, Eq, Hash)]
Компілятор зробить решту. Якщо ви хочете більше контролю над деталями,
ви можете реалізувати Eq і/або Hash самостійно.
Цей посібник не охоплюватиме специфіку реалізації Hash.
Щоб поекспериментувати з використанням struct у HashMap,
спробуймо зробити дуже просту систему входу користувача:
use std::collections::HashMap;
// Eq requires that you derive PartialEq on the type.
#[derive(PartialEq, Eq, Hash)]
struct Account<'a>{
username: &'a str,
password: &'a str,
}
struct AccountInfo<'a>{
name: &'a str,
email: &'a str,
}
type Accounts<'a> = HashMap<Account<'a>, AccountInfo<'a>>;
fn try_logon<'a>(accounts: &Accounts<'a>,
username: &'a str, password: &'a str){
println!("Username: {}", username);
println!("Password: {}", password);
println!("Attempting logon...");
let logon = Account {
username,
password,
};
match accounts.get(&logon) {
Some(account_info) => {
println!("Successful logon!");
println!("Name: {}", account_info.name);
println!("Email: {}", account_info.email);
},
_ => println!("Login failed!"),
}
}
fn main(){
let mut accounts: Accounts = HashMap::new();
let account = Account {
username: "j.everyman",
password: "password123",
};
let account_info = AccountInfo {
name: "John Everyman",
email: "[email protected]",
};
accounts.insert(account, account_info);
try_logon(&accounts, "j.everyman", "psasword123");
try_logon(&accounts, "j.everyman", "password123");
}