HashMapを存在しないキーで [] 添字アクセスすると no entry found for key パニックになる
HashMapに[]で添字アクセスした際、そのキーが存在しないとパニックします。存在するかどうか分からないキーを扱う場合は、getメソッドを使いOptionとして受け取る必要があります。
エラーメッセージの読み方
thread 'main' panicked at main.rs:5:24:
main.rs- ファイル名
5- 行番号 — 実際にクラッシュした行
24- 列番号
panicked- パニック — 実行時に回復不能な状態になったことを示します。tryやResultで捕まえない限り、そのままプロセスが終了します
no entry found for key- 詳細メッセージ — どの値が問題だったか
このエラーが出る典型パターン
パターン1
1 use std::collections::HashMap; 2 fn main() { 3 let mut ages: HashMap<&str, i32> = HashMap::new(); 4 ages.insert("taro", 20); 5 println!("{}", ages["hanako"]); ^ 6 }
HashMapの[]演算子は、存在しないキーを指定するとOptionを返さずその場でパニックします。
直し方: hanako を taro にします。
パターン2
1 use std::collections::HashMap; 2 fn main() { 3 let mut prices: HashMap<&str, i32> = HashMap::new(); 4 prices.insert("apple", 100); 5 println!("{}", prices["banana"]); ^ 6 }
存在するか分からないキーを扱う場合は、[]の代わりにgetを使いOptionとして受け取るべきです。
直し方: banana を apple にします。
パターン3
1 use std::collections::HashMap; 2 fn main() { 3 let mut stock: HashMap<&str, i32> = HashMap::new(); 4 stock.insert("pen", 5); 5 println!("{}", stock["pencil"]); ^ 6 }
配列の範囲外アクセスと違い、HashMapの欠損キーへのアクセスは常にパニックという形で現れます。
直し方: pencil を pen にします。
パターン4
1 use std::collections::HashMap; 2 fn main() { 3 let mut scores: HashMap<&str, i32> = HashMap::new(); 4 scores.insert("math", 90); 5 println!("{}", scores["science"]); ^ 6 }
登録していない科目名を指定すると、HashMapは静かにデフォルト値を返すことはせずパニックします。
直し方: science を math にします。
パターン5
1 use std::collections::HashMap; 2 fn main() { 3 let mut config: HashMap<&str, i32> = HashMap::new(); 4 config.insert("timeout", 30); 5 println!("{}", config["retries"]); ^ 6 }
設定値の読み出しでキー名を間違えると、実行時にパニックとして表面化します。
直し方: retries を timeout にします。
よくある誤解
「存在しないキーで参照すれば、配列の範囲外アクセスのようにnilや空の値が返るはず」という思い込みは誤りです。HashMapの[]演算子は見つからない場合にエラーを返さず、その場でパニックします。
実務での勘所
この挙動は特別な仕組みではなく、HashMapの[]演算子(Indexトレイトの実装)が、内部でget(key).expect("no entry found for key")のような処理を行っているだけです。表示されるパニックメッセージ自体が、標準ライブラリの内部で呼ばれているexpectの引数そのものです。つまりこれは、OptionやResultのunwrap・expectで見てきたのと同じ「グレースフルなデフォルトを用意しない」という設計を、[]という別の構文に対しても一貫して適用した結果です。