안녕하세요
오늘은 Rust의 Collection에 대해 알아보도록 하겠습니다
📌 컬렉션
Rust의 컬렉션은 대부분 std::collections 모듈에 정의돼 있습니다
주요 컬렉션 타입으로는 다음과 같습니다
타입 | 설명 | 특징 |
Vec<T> | 가변 크기 배열 (Vector) | 요소를 동적으로 추가 가능 |
String | 유니코드 문자열 | Vec<u8> 기반 |
HashMap<K, V> | 키-값 쌍 저장 | 해시 기반, 빠른 검색 |
HashSet<T> | 중복 없는 값 저장 | 내부적으로 HashMap<T, ()> |
LinkedList<T> | 양방향 연결 리스트 | 요소의 앞뒤 삽입에 효율적 |
VecDeque<T> | 양쪽에서 push/pop 가능 | 큐처럼 사용 가능 |
BinaryHeap<T> | 우선순위 큐 | 최대 힙 구조 |
BTreeMap<K, V> | 정렬된 키-값 저장 | 트리 기반 (순회 순서 보장) |
BTreeSet<T> | 정렬된 중복 없는 값 | BTreeMap<T, ()> 기반 |
📌 Vec<T>
Vec<T>는 가변 크기의 배열입니다
→ 크기를 동적으로 관리하는 컬렉션 입니다
✅ 생성
Vec::new() 또는 vec! 을 사용해서 Vector를 만들 수 있습니다
let v: Vec<i32> = Vec::new(); // 빈 벡터 생성
let v = vec![1, 2, 3]; // 초기값을 가진 벡터 생성
✅ 요소 추가 및 읽기
get 또는 []을 사용해 벡터 안의 값을 읽을 수 있습니다
- v.get(2) : 존재하지 않으면 None
- v[2] : 존재하지 않으면 panic!
fn main() {
let mut v = Vec::new(); // 타입 추론도 가능
v.push(10);
v.push(20);
v.push(30);
println!("첫 번째 값: {}", v[0]);
println!("세 번째 값: {}", v.get(2).unwrap()); // 안전하게 접근
}
✅ 반복문
벡터의 요소를 순회하기 위해 반복문을 사용할 수도 있습니다
fn main() {
let mut v = Vec::new();
v.push(10);
for x in &v {
println!("{}", x);
}
}
✅ 소유권
벡터는 값을 소유하고 있습니다
→ 값이 이동하면 원래 벡터는 그 값을 더 이상 사용할 수 없습니다
fn main() {
let mut v = vec![String::from("hello")];
let s = v.pop().unwrap(); // s는 "hello"를 가져감 (move)
println!("{}", s); // hello
// println!("{}", v[0]); // ❌ 에러: 값이 이미 이동됨
}
📌 HashMap<K, V>
HashMap<K, V>는 키-값 쌍을 저장하는 자료구조 입니다
✅ 생성 및 사용법
HashMap::new()를 통해 생성하고,
insert와 get으로 write/read 할 수 있습니다
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert("apple", 3);
map.insert("banana", 5);
println!("apple: {:?}", map.get("apple")); // Some(3)
println!("kiwi: {:?}", map.get("kiwi")); // None
}
✅ entry()와 or_insert()
특정 키가 없어 default 값을 넣고 싶은 경우에 사용할 수 있습니다
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert("Rust", 1);
// 값이 없으면 0을 넣고 그 참조를 반환
let count = map.entry("Go").or_insert(0);
*count += 1;
println!("{:?}", map); // {"Rust": 1, "Go": 1}
}
✅ 소유권
insert()는 값과 키를 소유합니다
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
let name = String::from("Alice");
map.insert(name, 10);
println!("{}", name); // name은 move 됐기 때문에 여기서 사용 불가
}
✅ vs BTreeMap
BTreeMap은 정렬이 필요할 때 사용합니다
use std::collections::{HashMap, BTreeMap};
fn main() {
let mut hmap = HashMap::new();
hmap.insert(3, "three");
hmap.insert(1, "one");
hmap.insert(2, "two");
println!("HashMap:");
for (k, v) in &hmap {
println!("{k}: {v}"); // 순서 보장 ❌
}
let mut bmap = BTreeMap::new();
bmap.insert(3, "three");
bmap.insert(1, "one");
bmap.insert(2, "two");
println!("\nBTreeMap:");
for (k, v) in &bmap {
println!("{k}: {v}"); // 순서 보장 ✅
}
}
📌 HashSet<T>
HashSet<T>는 중복 없는 값들의 집합을 표현하는 자료구조 입니다
✅ 생성 및 사용법
HashSet::new()로 생성하며,
insert와 contains 등을 사용할 수 있습니다
use std::collections::HashSet;
fn main() {
let mut set = HashSet::new();
set.insert("apple");
set.insert("banana");
set.insert("apple"); // 중복 삽입 → 무시됨
println!("set contains apple? {}", set.contains("apple")); // true
println!("set size: {}", set.len()); // 2
set.remove("banana");
println!("{:?}", set); // {"apple"}
}
✅ 집합 연산 메서드
수학의 집합처럼 다룰 수 있는 메서드도 있습니다
use std::collections::HashSet;
fn main() {
let a: HashSet<_> = [1, 2, 3].into_iter().collect();
let b: HashSet<_> = [3, 4, 5].into_iter().collect();
// 합집합
let union: HashSet<_> = a.union(&b).copied().collect();
println!("합집합: {:?}", union); // {1, 2, 3, 4, 5}
// 교집합
let intersection: HashSet<_> = a.intersection(&b).copied().collect();
println!("교집합: {:?}", intersection); // {3}
// 차집합
let difference: HashSet<_> = a.difference(&b).copied().collect();
println!("차집합 (a - b): {:?}", difference); // {1, 2}
// 대칭 차집합
let sym_diff: HashSet<_> = a.symmetric_difference(&b).copied().collect();
println!("대칭 차집합: {:?}", sym_diff); // {1, 2, 4, 5}
}
📌 VecDeque<T>
VecDeque<T>는 Double-Ended Queue (양방향 큐) 를 구현한 자료구조 입니다
front, back 양쪽에서 빠르게 push / pop 할 수 있습니다
✅ 생성 및 사용법
VecDeque::new()로 생성하고
push_back, pop_front 등을 사용할 수 있습니다
use std::collections::VecDeque;
fn main() {
let mut deque = VecDeque::new();
deque.push_back(1);
deque.push_back(2);
deque.push_front(0);
println!("{:?}", deque); // [0, 1, 2]
let front = deque.pop_front();
let back = deque.pop_back();
println!("front: {:?}, back: {:?}", front, back); // Some(0), Some(2)
println!("now: {:?}", deque); // [1]
}
'Rust' 카테고리의 다른 글
[Rust] 동시성 (0) | 2025.04.27 |
---|---|
[Rust] 에러 처리 (0) | 2025.03.30 |
[Rust] 스마트 포인터 (2) - RefCell<T>, Arc<T>, Mutex<T> (0) | 2025.03.24 |
[Rust] 스마트 포인터 (1) - Box<T>, Rc<T> (2) | 2025.03.24 |
[Rust] 제네릭(Generic), 트레잇(Trait), 동적 디스패처(dynamic dispatch) (2) | 2025.03.11 |