17.7.1 Alternate/custom key types
Eq와 Hash trait을 구현하는 모든 타입은 HashMap의 키가 될 수 있다. 다음을 포함:
bool(가능한 키가 두 개 뿐이라 유용하진 않음)int,uint, 과 이들의 모든 변수형String과&str(protip:String을 키로 갖는HashMap을 만들 수 있고&str로.get()을 호출할 수 있다.)
f32와 f64는 Hash를 구현하지 않는다, floating-point 정밀도 에러로 인해 에러가 발생하는 경향이 있기 때문이다.
모든 콜렉션 클래스들은 그들이 보관하는 타입들이 각기 Eq와 Hash를 구현했다면 Eq와 Hash를 구현한다. 예를 들어, Vec<T>는 T가 Hash를 구현했다면 Hash를 구현하게 될 것이다.
사용자 정의 타입에 단 한줄로 Eq와 Hash를 쉽게 구현할 수 있다:
#[derive(PartialEq, Eq, Hash)]
컴파일러가 나머지 작업을 수행하게 될 것이다. 보다 세밀하게 제어하고 싶다면, Eq와/나 Hash를 스스로 구현하면 된다. 이 가이드에서는 Hash 구현의 세부 사항을 다루지 않는다.
HashMap에서 구조체를 사용하는, 아주 간단한 사용자 로그온 시스템을 만들어보자.
use std::collections::HashMap;
// Eq는 PartialEq의 파생을 요구한다.
#[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: username,
password: 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");
}