Collezioni in Rust
La libreria standard di Rust offre diverse strutture dati nella module std::collections, ognuna ottimizzata per casi d’uso specifici.
Panoramica delle Collezioni
| Collezione | Descrizione | Caso d’uso |
|---|---|---|
Vec<T> |
Array dinamico | Lista ordinata, stack |
VecDeque<T> |
Coda a doppia estremitĂ | Coda FIFO, deque |
LinkedList<T> |
Lista doppiamente collegata | Inserimenti frequenti in mezzo |
HashMap<K,V> |
Mappa hash | Lookup per chiave O(1) |
BTreeMap<K,V> |
Mappa ordinata | Chiavi ordinate, range query |
HashSet<T> |
Insieme hash | UnicitĂ , appartenenza O(1) |
BTreeSet<T> |
Insieme ordinato | UnicitĂ con ordinamento |
BinaryHeap<T> |
Coda di prioritĂ | Elemento massimo rapido |
VecDeque
Coda efficiente per operazioni su entrambe le estremitĂ :
use std::collections::VecDeque;
fn main() {
let mut deque = VecDeque::new();
deque.push_back(1); // [1]
deque.push_back(2); // [1, 2]
deque.push_front(0); // [0, 1, 2]
println!("{:?}", deque.pop_front()); // Some(0)
println!("{:?}", deque.pop_back()); // Some(2)
}
HashMap
use std::collections::HashMap;
fn main() {
let mut mappa = HashMap::new();
mappa.insert("chiave", 42);
// Entry API
mappa.entry("chiave").or_insert(0);
*mappa.entry("nuova").or_insert(0) += 1;
// Conteggio occorrenze
let testo = "ciao mondo ciao rust ciao";
let mut conteggio = HashMap::new();
for parola in testo.split_whitespace() {
*conteggio.entry(parola).or_insert(0) += 1;
}
println!("{:?}", conteggio); // {"ciao": 3, "mondo": 1, "rust": 1}
}
BTreeMap
Come HashMap ma con chiavi ordinate:
use std::collections::BTreeMap;
fn main() {
let mut mappa = BTreeMap::new();
mappa.insert(3, "tre");
mappa.insert(1, "uno");
mappa.insert(2, "due");
// Iterazione in ordine di chiave
for (k, v) in &mappa {
println!("{}: {}", k, v); // 1: uno, 2: due, 3: tre
}
// Range query
for (k, v) in mappa.range(1..=2) {
println!("{}: {}", k, v);
}
}
HashSet
Insieme di valori unici:
use std::collections::HashSet;
fn main() {
let mut set = HashSet::new();
set.insert(1);
set.insert(2);
set.insert(2); // Duplicato ignorato
println!("{}", set.contains(&1)); // true
println!("{}", set.len()); // 2
// Operazioni insiemistiche
let a: HashSet<i32> = [1, 2, 3].into();
let b: HashSet<i32> = [2, 3, 4].into();
let unione: HashSet<_> = a.union(&b).collect();
let intersezione: HashSet<_> = a.intersection(&b).collect();
let differenza: HashSet<_> = a.difference(&b).collect();
println!("Unione: {:?}", unione); // {1, 2, 3, 4}
println!("Intersezione: {:?}", intersezione); // {2, 3}
println!("Differenza: {:?}", differenza); // {1}
}
BinaryHeap
Coda di prioritĂ (max-heap):
use std::collections::BinaryHeap;
fn main() {
let mut heap = BinaryHeap::new();
heap.push(3);
heap.push(1);
heap.push(4);
heap.push(1);
heap.push(5);
// Estrae sempre il massimo
println!("{:?}", heap.pop()); // Some(5)
println!("{:?}", heap.pop()); // Some(4)
println!("{:?}", heap.peek()); // Some(&3) (guarda senza estrarre)
}
Come Scegliere
- Sequenza ordinata →
Vec<T> - Coda FIFO →
VecDeque<T> - Lookup per chiave →
HashMap<K,V> - Chiavi ordinate →
BTreeMap<K,V> - Valori unici →
HashSet<T> - Priorità →
BinaryHeap<T>
Conclusione
Rust offre un set completo di collezioni nella libreria standard, ognuna con caratteristiche di performance specifiche. Vec e HashMap coprono la maggior parte dei casi d’uso. Usa le varianti BTree quando serve ordinamento e BinaryHeap per code di priorità . La scelta della collezione giusta può avere un impatto significativo sulle performance dell’applicazione.