대체/사용자 정의 키 타입
Eq와 Hash 트레이트를 구현하는 어떤 타입이든 HashMap의 키가 될 수 있습니다. 여기에는 다음이 포함됩니다:
bool(가능한 키가 두 개뿐이라 그리 유용하진 않지만요)int,uint및 그 모든 변형들String과&str(꿀팁:String을 키로 하는HashMap을 만들고&str을 사용하여.get()을 호출할 수 있습니다)
f32와 f64는 Hash를 구현하지 않는다는 점에 유의하세요. 아마도 부동 소수점 정밀도 에러로 인해 이들을 해시 맵 키로 사용하는 것이 극도로 에러에 취약해질 수 있기 때문일 것입니다.
모든 컬렉션 클래스는 포함된 타입이 각각 Eq와 Hash를 구현한다면 Eq와 Hash를 구현합니다. 예를 들어, Vec<T>는 T가 Hash를 구현한다면 Hash를 구현합니다.
단 한 줄의 코드로 커스텀 타입에 대해 Eq와 Hash를 쉽게 구현할 수 있습니다: #[derive(PartialEq, Eq, Hash)]
컴파일러가 나머지를 알아서 할 것입니다. 만약 세부 사항을 더 제어하고 싶다면, Eq나 Hash를 직접 구현할 수 있습니다. 이 가이드에서는 Hash 구현의 구체적인 내용은 다루지 않습니다.
HashMap에서 struct를 사용하는 것을 연습해 보기 위해, 매우 간단한 사용자 로그인 시스템을 만들어 봅시다:
use std::collections::HashMap;
// Eq는 해당 타입에 대해 PartialEq를 유도(derive)할 것을 요구합니다.
#[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);
println!("비밀번호: {}", password);
println!("로그인 시도 중...");
let logon = Account {
username,
password,
};
match accounts.get(&logon) {
Some(account_info) => {
println!("로그인 성공!");
println!("이름: {}", account_info.name);
println!("이메일: {}", account_info.email);
},
_ => println!("로그인 실패!"),
}
}
fn main(){
let mut accounts: Accounts = HashMap::new();
let account = Account {
username: "j.everyman",
password: "password123",
};
let account_info = AccountInfo {
name: "John Everyman",
email: "j.everyman@email.com",
};
accounts.insert(account, account_info);
try_logon(&accounts, "j.everyman", "psasword123");
try_logon(&accounts, "j.everyman", "password123");
}