HashMapは、キーと値のペアを保存するために使えるコンテナです。他のプログラミング言語では、このデータ構造は連想配列やハッシュテーブルと呼ばれることもあります。マップはキーの集合を持ち、それぞれのキーが特定の値に対応づけられています。適切なキーを渡すことで、保存した値を取り出すことができます。キーとそれに対応する値の挿入や削除もできます。
HashMapは(標準ライブラリのほとんどのコレクションと同じように)ジェネリックなコレクションなので、ユーザー定義の構造体やタプルなど、幅広い型をキーとして使えます。値にはどんな型でも使えます。
HashMapの作成HashMapはHashMap::new()関数で作成します。次のコードは、チーム名をスコアに対応づけたHashMapを作成します。
use std::collections::HashMap;
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
HashMapの値へのアクセス値がHashMap内に存在することがわかっている場合は、インデックス演算子([])を使うのが適切です。たとえば、青チームのスコアを取り出すには、scores["Blue"]と書きます。ただし、対応するキーと値のペアがHashMap内に存在しない場合、この操作はパニックになります。
インデックス演算子のほかにも、HashMapに保存された値にアクセスする方法が2つあります。1つはgetメンバー関数を使う方法です。
if let Some(blue_score) = scores.get("Blue") {
println!("Blue scored: {blue_score} \n");
}
getは、要求したキーに対応して保存されている値にアクセスします。指定したキーがHashMapに存在しなければNoneを返し、キーが存在すればSome(value)を返します。RustのOptionsについて詳しくは、Optionsのコンセプトを参照してください。
HashMapに保存された値にアクセスするもう1つの方法は、entryメソッドを使うことです。entryメソッド(またはentry API)は、HashMap内のキーと値のペアのエントリーへの参照を返します。エントリーは、このキーのハッシュ内での状態を表します。キーが存在しなければ、エントリーには値がなく(新しく挿入できるようになっています)。
let mut vote_counter: HashMap<_, usize> = HashMap::new();
let votes = ["Blue", "Red", "Red", "Blue", "Red", "Blue", "Blue"];
for vote in votes {
let count = vote_counter.entry(vote).or_default();
*count += 1;
}
println!("{vote_counter:#?}");
このAPIは、よくあるアクセスパターンをとても便利にします。専用のコンセプト(Entry API)が1つ設けられているほどです。
HashMapは比較的高速で、1つのキーを扱うすべての操作が償却定数時間の計算量(O(1))です。
HashMapはジェネリックなデータ構造です。つまり、キーと値に任意の型を使えますが、制約が1つだけあります。ある型をキーの型として使うには、2つのトレイトEqとHashを実装している必要があります。値の型にはトレイト境界はありません。