代替/カスタムキー型
Eq トレイトと Hash トレイトを実装する任意の型は、HashMap のキーにできます。 これには以下が含まれます。
bool(可能なキーが 2 つしかないため、あまり有用ではありません)int、uint、およびそれらのすべてのバリエーションStringと&str(豆知識:StringをキーとするHashMapを持ち、&strで.get()を呼び出すことができます)
f32 と f64 は Hash を実装して_いない_ことに注意してください。 おそらく、浮動小数点数の精度誤差により、 それらをハッシュマップのキーとして使用すると非常にエラーを起こしやすくなるためです。
すべてのコレクションクラスは、含まれる型もそれぞれ Eq と Hash を実装していれば、 Eq と Hash を実装します。 たとえば、Vec<T> は、T が Hash を実装していれば Hash を実装します。
カスタム型に対して Eq と Hash を実装するのは、たった 1 行で簡単にできます。 #[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"); }