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"); }