Rustのデータ構造ガイド:ベクター、ハッシュマップ、セットなど
Grace Collins
Solutions Engineer · Leapcell

Rustの標準ライブラリは、ベクター(Vec<T>
)、ハッシュマップ(HashMap<K, V>
)、ハッシュセット(HashSet<T>
)などの基本的なデータ構造を提供します。これらの3つのデータ構造は、最も一般的に使用され、ほとんどのプログラミングシナリオで役立ちます。その設計は、安全で、同時実行可能で、実用的なプログラミング言語を提供するというRustの目標と一致しています。これらの構造は、Rustの標準ライブラリの軽量で効率的な性質を維持しながら、ほとんどのデータストレージとアクセスニーズをカバーします。
ベクター(Vec<T>
)
ベクターは、Rustで最も一般的に使用される動的配列の実装です。高速なインデックスアクセス、動的なサイズ変更、および効率的な走査を提供します。これは、連続したメモリストレージによるもので、最新のCPUキャッシュメカニズムを活用します。
fn main() { // 空のベクターを作成 let mut numbers: Vec<i32> = Vec::new(); // マクロを使用してベクターを作成および初期化 let mut names = vec!["Alice", "Bob", "Carol"]; // ベクターに要素を追加 numbers.push(1); numbers.push(2); numbers.push(3); // ベクターから要素を削除 numbers.pop(); // 最後の要素を削除して返す // ベクター内の要素にアクセス if let Some(first_name) = names.get(0) { println!("The first name is: {}", first_name); } // ベクター要素を反復処理 for name in &names { println!("{}", name); } // ベクター内の要素を変更 if let Some(first_name) = names.get_mut(0) { *first_name = "Dave"; } // イテレーターを使用してベクター要素を処理 let numbers_squared: Vec<i32> = numbers.iter().map(|&x| x * x).collect(); println!("Squared numbers: {:?}", numbers_squared); // ベクターを追加の要素で拡張 numbers.extend([4, 5, 6].iter().copied()); // インデックスを使用して要素に直接アクセス println!("Second name: {}", names[1]); // 注:直接インデックスはパニックになる可能性があります }
ベクターは、文字列、整数、またはカスタムタイプなど、同じ型の要素のシーケンスを処理するのに理想的です。要素の追加、削除、およびランダムアクセスが簡単に行えます。
ハッシュマップ(HashMap<K, V>
)
ハッシュマップは、ハッシュテーブルを使用して実装されたキーと値のストレージを提供します。高速な検索、挿入、および削除をサポートし、効率的なデータ取得と管理に不可欠なデータ構造です。
use std::collections::HashMap; fn main() { // 空のハッシュマップを作成 let mut book_reviews: HashMap<String, String> = HashMap::new(); // ハッシュマップに要素を追加 book_reviews.insert("The Hobbit".to_string(), "Excellent fantasy book".to_string()); book_reviews.insert("The Catcher in the Rye".to_string(), "Classic novel".to_string()); // ハッシュマップ内の要素にアクセス if let Some(review) = book_reviews.get("The Hobbit") { println!("Review of The Hobbit: {}", review); } // ハッシュマップから要素を削除 book_reviews.remove("The Catcher in the Rye"); // ハッシュマップを反復処理 for (book, review) in &book_reviews { println!("{}: {}", book, review); } // ハッシュマップ内の要素を更新 book_reviews.entry("The Hobbit".to_string()).or_insert("No review found".to_string()); book_reviews.entry("1984".to_string()).or_insert("Dystopian science fiction".to_string()); let mut scores = HashMap::new(); // `insert`を使用して直接挿入 scores.insert("Blue", 10); scores.insert("Blue", 25); // 以前の値を上書き // `entry`を使用して更新または挿入 scores.entry("Yellow").or_insert(50); // 「Yellow」が存在しないため挿入 scores.entry("Blue").or_insert(50); // 「Blue」が既に存在するため何もしない // 結果:{"Blue": 25, "Yellow": 50} // キーが存在するかどうかを確認 if book_reviews.contains_key("1984") { println!("Review for 1984 is available."); } }
ハッシュマップは、データベースのインデックス作成やキャッシュの実装など、キーを使用してデータにすばやくアクセスする必要がある場合に役立ちます。柔軟なキーと値の関連付けを提供し、データの編成と取得を簡単かつ効率的にします。
ハッシュセット(HashSet<T>
)
ハッシュセットは、一意の要素を格納する順序付けられていないコレクションです。ハッシュテーブルを使用して実装され、高速な検索、挿入、および削除操作を提供します。
use std::collections::HashSet; fn main() { // 空のセットを作成 let mut numbers = HashSet::new(); // セットに要素を追加 numbers.insert(1); numbers.insert(2); numbers.insert(3); // セットから要素を削除 numbers.remove(&3); // セットに要素が存在するかどうかを確認 if numbers.contains(&1) { println!("1 is in the set"); } // セットを反復処理 for number in &numbers { println!("{}", number); } // セット演算:和集合、積集合、差集合、対称差 // この時点で、numbersには{1, 2}が含まれています let other_numbers = [2, 3, 4].iter().cloned().collect::<HashSet<_>>(); // other_numbersには{2, 3, 4}が含まれています let union = numbers.union(&other_numbers).cloned().collect::<HashSet<_>>(); println!("Union: {:?}", union); // 和集合:`{1, 2, 3, 4}`(両方のセットからのすべての一意の要素) let intersection = numbers.intersection(&other_numbers).cloned().collect::<HashSet<_>>(); println!("Intersection: {:?}", intersection); // 積集合:`{2}`(共通要素) let difference = numbers.difference(&other_numbers).cloned().collect::<HashSet<_>>(); println!("Difference: {:?}", difference); // 差集合:`{1}`(`numbers`にはあるが`other_numbers`にはない要素) let symmetric_difference = numbers.symmetric_difference(&other_numbers).cloned().collect::<HashSet<_>>(); println!("Symmetric Difference: {:?}", symmetric_difference); // 対称差:`{1, 3, 4}`(各セットに固有の要素) }
ハッシュセットは、ユーザーIDリストや特定の条件下でのレコードなど、一意の要素のコレクションを処理する場合に特に役立ちます。和集合、積集合、差集合などのセット演算は、コレクションデータを効率的に処理するための強力なツールを提供します。
双方向連結リスト(LinkedList<T>
)
LinkedList<T>
は、Rustの標準ライブラリによって提供される双方向連結リストです。ベクター(Vec<T>
)と比較して、連結リストでは、特にリストの先頭または末尾での要素の挿入と削除が効率的に行えます。ただし、ランダムアクセスではパフォーマンスが低下します。
use std::collections::LinkedList; fn main() { // 新しい空の連結リストを作成 let mut list: LinkedList<i32> = LinkedList::new(); // リストの末尾に要素を追加 list.push_back(1); list.push_back(2); // リストの先頭に要素を追加 list.push_front(0); // リストの先頭と末尾から要素をポップ assert_eq!(list.pop_front(), Some(0)); assert_eq!(list.pop_back(), Some(2)); // リストを反復処理 for elem in list.iter() { println!("{}", elem); } // リスト内の要素を変更(イテレーターを使用する必要がある) let mut iter_mut = list.iter_mut(); if let Some(first_elem) = iter_mut.next() { *first_elem = 3; } // 変更されたリストを出力 println!("Modified list: {:?}", list); }
リストの先頭または末尾での頻繁な追加または削除が必要な場合、LinkedList
は、これらの操作の時間計算量がO(1)であるため、優れた選択肢です。
アプリケーションでランダムアクセスがほとんど必要なく、シーケンシャルな走査に重点を置いている場合は、連結リストの方がベクターよりも適している場合があります。
B-Tree Map(BTreeMap<K, V>
)
BTreeMap<K, V>
は、B-Treeを使用して実装されたキーと値のコレクションです。キーをソートされた順序で保持します。ハッシュマップ(HashMap<K, V>
)と比較して、BTreeMap
は、順序付けられたキー、範囲検索、または順序付けられた走査が必要な場合に優れています。
use std::collections::BTreeMap; fn main() { // 新しい空のBTreeMapを作成 let mut map: BTreeMap<String, i32> = BTreeMap::new(); // キーと値のペアをBTreeMapに挿入 map.insert("apple".to_string(), 3); map.insert("banana".to_string(), 2); map.insert("pear".to_string(), 4); // キーに対応する値を取得 if let Some(v) = map.get("apple") { println!("apple: {}", v); } // キーと値のペアを削除 map.remove("banana"); // BTreeMapを反復処理 for (key, value) in &map { println!("{}: {}", key, value); } // 範囲クエリ:キーが「apple」と「pear」の間(包括的)のすべてのキーと値のペアを取得 let range = map.range("apple".to_string()..="pear".to_string()); for (key, value) in range { println!("Range query: {}: {}", key, value); } }
BTreeMap
は、自動的にソートされたマップが必要な場合に適したオプションです。特に、範囲クエリと順序付けられた走査に役立ちます。
プログラムが、キーが自然に順序付けられているルックアップや挿入、削除操作を頻繁に実行する場合、BTreeMap
はキーの順序を維持し、範囲ルックアップと順序付けられた走査を容易にするため、HashMap
よりも適している場合があります。
B-Tree Set(BTreeSet<T>
)
BTreeSet<T>
は、B-Treeに基づいて実装されたセットです。一意の要素を格納し、ソートされた順序で保持します。HashSet<T>
と比較して、BTreeSet
は順序付けられた操作と範囲クエリをサポートしますが、一部の操作では遅くなる可能性があります。
use std::collections::BTreeSet; fn main() { // 新しい空のBTreeSetを作成 let mut set: BTreeSet<i32> = BTreeSet::new(); // セットに要素を追加 set.insert(12); set.insert(5); set.insert(18); // 要素が存在するかどうかを確認 if set.contains(&12) { println!("Set contains 12"); } // 要素を削除 set.remove(&5); // セットを反復処理(要素は昇順になります) for num in &set { println!("{}", num); } // 範囲クエリ:10以上20未満のすべての要素を取得 for num in set.range(10..20) { println!("Range query: {}", num); } }
BTreeSet
は、高速なルックアップ、範囲クエリ、または順序付けられた走査のために順序付けられたセットが必要な場合に適した選択肢です。
一意の要素を格納する必要があり、要素が比較可能な関係を持っているシナリオに適しています。
バイナリヒープ(BinaryHeap<T>
)
BinaryHeap<T>
は、バイナリヒープに基づく優先度付きキューの実装です。要素の高速な挿入と、最大(または最小)要素の削除が可能です。デフォルトでは、RustのBinaryHeap
は最大ヒープです。
use std::collections::BinaryHeap; fn main() { // 新しい空のBinaryHeapを作成 let mut heap = BinaryHeap::new(); // ヒープに要素を追加 heap.push(1); heap.push(5); heap.push(2); // 削除せずにヒープ内の最大要素をピーク if let Some(max) = heap.peek() { println!("Max element: {}", max); } // 最大要素を削除して返す println!("Removed max element: {}", heap.pop().unwrap()); // ヒープを反復処理(反復の順序はソートされていません) for num in &heap { println!("{}", num); } }
最大(または最小)要素への高速アクセスと削除に必要なデータ構造が必要な場合は、BinaryHeap
が理想的です。これは、ダイクストラの最短経路などのアルゴリズムで特に役立ちます。
BinaryHeap
は、タスクスケジューリング、貪欲アルゴリズム、または優先度付きキューを必要とするあらゆるシナリオに適しています。
Leapcellは、Rustプロジェクトをホストするための最良の選択肢です。
Leapcellは、Webホスティング、非同期タスク、およびRedis向けの次世代サーバーレスプラットフォームです。
多言語サポート
- Node.js、Python、Go、またはRustで開発します。
無制限のプロジェクトを無料でデプロイ
- 使用量に対してのみ支払い - リクエストなし、料金なし。
比類のないコスト効率
- アイドル料金なしの従量課金制。
- 例:25ドルで、平均応答時間60ミリ秒で694万リクエストをサポートします。
合理化された開発者エクスペリエンス
- 簡単なセットアップのための直感的なUI。
- 完全に自動化されたCI/CDパイプラインとGitOps統合。
- 実行可能な洞察のためのリアルタイムメトリクスとロギング。
簡単なスケーラビリティと高性能
- 高い同時実行性を容易に処理するための自動スケーリング。
- 運用オーバーヘッドゼロ - 構築に集中するだけです。
ドキュメントで詳細をご覧ください!
Xでフォローしてください:@LeapcellHQ