Rustのコレクション: Vec、String、HashMap
Rustの標準コレクション(順序付きリストのVector、UTF-8テキストのString、キー・バリューペアのHashMap)を使用してヒープ上に動的データを格納します。
Rust基礎シリーズの第9回です。コンパイル時にサイズが固定される配列やタプルとは異なり、コレクションはヒープ上に割り当てられたデータを指し、実行時に動的に伸縮できます。
graph TD
subgraph Collections["Rust Standard Collections"]
Vec["Vec<T><br/>Dynamically sized ordered list"]
String["String<br/>UTF-8 encoded bytes wrapper"]
HashMap["HashMap<K, V><br/>Key-Value lookup table"]
end
subgraph Memory["Memory Layout"]
Stack["Stack: Pointer + Capacity + Length"]
Heap["Heap: Dynamic buffer allocation"]
end
Vec --> Stack
String --> Stack
HashMap --> Stack
Stack -->|points to| Heap
ベクター (Vec<T>)#
ベクターは、同じ型の複数の値をメモリ上に連続して格納します。
graph LR
subgraph StackMem["Stack Memory"]
V["vec"]
V_ptr["ptr"]
V_cap["cap: 4"]
V_len["len: 3"]
end
subgraph HeapMem["Heap Memory"]
H0["[0]: 10"]
H1["[1]: 20"]
H2["[2]: 30"]
H3["[3]: Unallocated"]
end
V_ptr --> H0
H0 --- H1 --- H2 --- H3
fn main() {
let mut v: Vec<i32> = Vec::new();
v.push(10);
v.push(20);
v.push(30);
// vec! マクロの使用
let v2 = vec![1, 2, 3];
// get() による安全な要素アクセス
match v.get(1) {
Some(third) => println!("2番目の要素は {third} です"),
None => println!("2番目の要素は存在しません。"),
}
// イテレーション
for i in &v {
println!("{i}");
}
}rustUTF-8 文字列 (String)#
Rustにおいて、String は有効なUTF-8テキストであることが保証された Vec<u8> のラッパーです。
graph LR
subgraph StackFrame["Stack Frame"]
S["s (String)"]
S_ptr["ptr"]
S_cap["cap: 7"]
S_len["len: 7"]
end
subgraph HeapBuffer["Heap Buffer"]
B0["'f' (102)"]
B1["'o' (111)"]
B2["'o' (111)"]
B3["'b' (98)"]
B4["'a' (97)"]
B5["'r' (114)"]
B6["'!' (33)"]
end
S_ptr --> B0
B0 --- B1 --- B2 --- B3 --- B4 --- B5 --- B6
let mut s = String::from("foo");
s.push_str("bar");
s.push('!');
// + または format! による文字列連結
let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = format!("{s1}{s2}"); // format! は所有権を奪いませんrustUTF-8文字はバイト長が可変(1〜4バイト)であるため、無効な文字バイトを返すリスクを防ぐためRustでは s[0] のような直接インデックス指定はサポートされていません。代わりに文字列スライス &s[0..4] を使用するか、.chars() で反復処理を行います。
ハッシュマップ (HashMap<K, V>)#
ハッシュマップは、ハッシュ関数を使用して型 K のキーを型 V の値にマッピングします。
graph LR
subgraph HashFunc["Hash Function"]
K1["Key: 'Blue'"] --> H1["Hash('Blue')"]
K2["Key: 'Yellow'"] --> H2["Hash('Yellow')"]
end
subgraph BucketArray["Bucket Array on Heap"]
H1 --> B1["Bucket 2: ('Blue', 10)"]
H2 --> B2["Bucket 5: ('Yellow', 50)"]
end
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
// 値へのアクセス
let team_name = String::from("Blue");
let score = scores.get(&team_name).copied().unwrap_or(0);
println!("Blueチームのスコア: {score}");
// entry APIによるキー不在時のみの挿入
scores.entry(String::from("Blue")).or_insert(25);
scores.entry(String::from("Red")).or_insert(100);
for (key, value) in &scores {
println!("{key}: {value}");
}
}rustまとめ#
ベクターは順序付き要素リストを、Stringはヒープ割り当てのUTF-8テキストを安全に管理し、HashMapはキーと値の関連付けを管理します。シリーズの次回テーマは「エラー処理」です。