集合型別(Vec 與 HashMap)#
集合(Collection) 是可以儲存多個值的資料結構。
不同於固定大小的陣列,集合的長度可以在執行時動態增減,資料存放在 堆積(Heap) 上。
Rust 標準函式庫提供多種集合,其中最常用的是 Vec<T> (動態陣列)和 HashMap<K, V> (雜湊映射)。
1. Vec — 動態陣列#
Vec<T> 儲存一系列 相同型別 的值,依序排列,可以動態增減長度。
建立 Vec#
1
2
3
4
5
6
7
| fn main() {
// 方法一:空 Vec,需明確標注型別
let v: Vec<i32> = Vec::new();
// 方法二:用 vec! 巨集,型別自動推斷
let v = vec![1, 2, 3, 4, 5];
}
|
新增元素#
1
2
3
4
5
6
7
| fn main() {
let mut v = Vec::new();
v.push(1);
v.push(2);
v.push(3);
println!("{:?}", v); // [1, 2, 3]
}
|
Vec 必須宣告為 mut 才能修改。
存取元素#
兩種存取方式,差別在於越界時的行為:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| fn main() {
let v = vec![10, 20, 30];
// 方法一:索引(超出範圍會 panic)
println!("{}", v[0]); // 10
// 方法二:get(),回傳 Option<&T>,安全不 panic
match v.get(2) {
Some(val) => println!("第三個元素:{val}"), // 30
None => println!("索引超出範圍"),
}
println!("{:?}", v.get(10)); // None
}
|
推薦使用 get() 避免程式意外 panic。
迭代 Vec#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| fn main() {
let v = vec![1, 2, 3];
// 不可變迭代(借用)
for n in &v {
println!("{n}"); // n 的型別是 &i32
}
// 可變迭代(修改元素)
let mut v = vec![1, 2, 3];
for n in &mut v {
*n *= 2; // 解參考後修改
}
println!("{:?}", v); // [2, 4, 6]
}
|
常用方法#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| fn main() {
let mut v = vec![3, 1, 4, 1, 5, 9, 2, 6];
println!("長度:{}", v.len()); // 8
println!("是否為空:{}", v.is_empty()); // false
v.push(7); // 尾端新增
let last = v.pop(); // 移除並回傳尾端元素,型別是 Option<T>
println!("{:?}", last); // Some(7)
v.sort();
println!("{:?}", v); // [1, 1, 2, 3, 4, 5, 6, 9]
println!("包含 5:{}", v.contains(&5)); // true
}
|
2. HashMap — 雜湊映射#
HashMap<K, V> 儲存 鍵值對(key-value pair) ,透過鍵快速查詢對應的值。
使用前需引入:
1
| use std::collections::HashMap;
|
建立與插入#
1
2
3
4
5
6
7
8
9
10
| use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Alice"), 100);
scores.insert(String::from("Bob"), 85);
println!("{:?}", scores);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Alice"), 100);
scores.insert(String::from("Bob"), 85);
// get() 回傳 Option<&V>
let alice = scores.get("Alice");
println!("{:?}", alice); // Some(100)
// 直接用 [] 存取(鍵不存在會 panic)
println!("{}", scores["Bob"]); // 85
// 判斷鍵是否存在
println!("{}", scores.contains_key("Carol")); // false
}
|
更新值#
1
2
3
4
5
6
7
8
9
10
| use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Alice"), 100);
// 直接覆蓋舊值
scores.insert(String::from("Alice"), 110);
println!("{:?}", scores.get("Alice")); // Some(110)
}
|
entry API — 不存在才插入#
entry() 是更新 HashMap 最慣用的方式,避免多餘的查詢:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Alice"), 100);
// "Bob" 不存在,插入 0
scores.entry(String::from("Bob")).or_insert(0);
// "Alice" 已存在,不做任何事
scores.entry(String::from("Alice")).or_insert(0);
println!("{:?}", scores);
// {"Alice": 100, "Bob": 0}
}
|
or_insert() 回傳該鍵對應值的 &mut V,可以直接修改。以下是統計單字出現次數的經典寫法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| use std::collections::HashMap;
fn main() {
let text = "hello world hello rust hello";
let mut word_count = HashMap::new();
for word in text.split_whitespace() {
let count = word_count.entry(word).or_insert(0);
*count += 1; // 解參考後累加
}
println!("{:?}", word_count);
// {"hello": 3, "world": 1, "rust": 1}
}
|
迭代 HashMap#
1
2
3
4
5
6
7
8
9
10
11
12
13
| use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert("Alice", 100);
scores.insert("Bob", 85);
scores.insert("Carol", 92);
// 迭代順序不固定
for (name, score) in &scores {
println!("{name}: {score}");
}
}
|
常用方法#
1
2
3
4
5
6
7
8
9
10
11
12
13
| use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert("a", 1);
map.insert("b", 2);
println!("長度:{}", map.len()); // 2
println!("含鍵 a:{}", map.contains_key("a")); // true
map.remove("a");
println!("移除後長度:{}", map.len()); // 1
}
|
3. Vec 與 HashMap 比較#
| Vec<T> | HashMap<K, V> |
|---|
| 用途 | 有序元素清單 | 鍵值對查詢 |
| 存取方式 | 索引(v[i]) | 鍵(map[key]) |
| 平均存取速度 | O(1) | O(1) |
| 使用場景 | 資料清單、堆疊、佇列 | 計數、索引、快取 |
需要 use | 不需要 | use std::collections::HashMap |
Reference#
https://doc.rust-lang.org/book/ch08-00-common-collections.html