問題の歴史
HashSetおよびHashMapコレクションは、ハッシュによる高速な検索を実現する標準的な構造で、std::collectionsに含まれています。これらはRustの初期のバージョンから組み込まれていますが、その内部的な詳細の使用は、所有権システムのために経験豊富な開発者でもしばしば困難を引き起こします。
問題
特に値がCopyでない場合、要素の挿入や抽出中に混乱が生じたり、コレクションの変更(可変借用)、またキーとして参照を使用する際にも問題が発生します。さらに、ユーザー定義型に対する適切なEq/Hashの実装に関する問題もあります。
解決策
コードの例:
use std::collections::HashMap; fn main() { let mut map = HashMap::new(); map.insert("key", 42); if let Some(value) = map.get("key") { println!("Found value: {}", value); } }
主な特性:
HashMapの同じ要素に対して複数の可変参照を取得できますか?
いいえ、所有権の違反を避けるために借用チェッカーはこれを許可しません。
文字列リテラル"abc"をHashMap<String, V>のキーとして直接使用できますか?
いいえ、Stringが期待されており、"abc"は&'static strです。変換が必要です: insert("abc".to_string(), val)。
値をHashMapから抽出し、別の変数に保存した後、HashMapを引き続き使用できますか?
はい、getを通じて値への参照を取得できますが、remove(またはmoveで抽出)を行うとHashMapが変わり、古いすべての参照が無効になります。
キーと値の両方を同時に借用し、その後コレクションを変更しようとする:
let mut map = HashMap::new(); map.insert("abc".to_string(), 10); let val = map.get("abc"); map.insert("def".to_string(), 20); // borrow checkerエラー
長所:
短所:
値を抽出し、そのコピーまたはクローンのみを使用する:
let mut map = HashMap::new(); map.insert("abc".to_string(), 10); if let Some(val) = map.get("abc") { let val = *val; // コピーする map.insert("def".to_string(), 20); // すべて動作する }
長所:
短所: