Collection trong Rust: Vec, String, HashMap
Lưu trữ dữ liệu động trên heap với các kiểu collection chuẩn trong Rust: vector cho danh sách có thứ tự, string cho văn bản UTF-8 và HashMap cho cặp key-value.
Bài thứ chín trong loạt Rust cơ bản. Khác với mảng và tuple cố định kích thước từ lúc biên dịch, collection trỏ đến dữ liệu cấp phát trên heap và có thể mở rộng hoặc thu nhỏ linh hoạt trong khi chạy.
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
Vector (Vec<T>)#
Vector lưu trữ nhiều giá trị cùng kiểu dữ liệu liên tiếp nhau trong bộ nhớ:
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);
// Dùng macro vec!
let v2 = vec![1, 2, 3];
// Truy cập an toàn với get()
match v.get(1) {
Some(third) => println!("Phần tử thứ hai là {third}"),
None => println!("Không có phần tử thứ hai."),
}
// Duyệt qua các phần tử
for i in &v {
println!("{i}");
}
}rustChuỗi UTF-8 (String)#
Trong Rust, String là một wrapper bọc quanh Vec<u8> được đảm bảo là văn bản UTF-8 hợp lệ:
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('!');
// Nối chuỗi với + hoặc format!
let s1 = String::from("Xin chào, ");
let s2 = String::from("Rust!");
let s3 = format!("{s1}{s2}"); // format! không lấy quyền sở hữu của s1, s2rustDo ký tự UTF-8 có độ dài byte thay đổi (từ 1 đến 4 byte), Rust không hỗ trợ truy cập chỉ số trực tiếp như s[0] để tránh trả về byte ký tự không hợp lệ. Thay vào đó, hãy dùng string slice &s[0..4] hoặc duyệt qua .chars().
Hash Map (HashMap<K, V>)#
Hash map ánh xạ các khóa (key) kiểu K tới các giá trị (value) kiểu V thông qua hàm băm (hashing):
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);
// Truy cập giá trị
let team_name = String::from("Blue");
let score = scores.get(&team_name).copied().unwrap_or(0);
println!("Điểm đội Blue: {score}");
// Chỉ chèn nếu khóa chưa tồn tại bằng 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}");
}
}rustKết luận#
Vector lưu trữ danh sách phần tử có thứ tự, String quản lý văn bản UTF-8 cấp phát trên heap an toàn, và HashMap quản lý liên kết cặp key-value. Bài tiếp theo trong loạt: xử lý lỗi.