iter()
The .iter() method is a convention on slices ([T]) and standard collections (Vec<T>, VecDeque<T>, HashSet<T>, BTreeSet<T>) that borrows the collection immutably (&self) and returns an iterator yielding shared references (&T) to each element.
Signature and Item Type
On a slice [T] (and on Vec<T> via deref coercion), .iter() has the signature:
pub fn iter(&self) -> std::slice::Iter<'_, T>
// where Iter<'a, T>: Iterator<Item = &'a T>
Because .iter() only borrows the collection with &self, the collection remains intact and fully usable after iteration completes:
fn main() {
let languages = vec![String::from("Rust"), String::from("C"), String::from("Zig")];
// `.iter()` yields `&String`; `languages` is borrowed immutably, not consumed:
for lang in languages.iter() {
println!("Language: {lang} ({} bytes)", lang.len());
}
// `languages` is still owned and valid here:
println!("Collection still has {} items: {languages:?}", languages.len());
}
Language: Rust (4 bytes)
Language: C (1 bytes)
Language: Zig (3 bytes)
Collection still has 3 items: ["Rust", "C", "Zig"]
equivalence of collection.iter() and for x in &collection
Standard collections implement IntoIterator for &Collection by delegating directly to .iter(). Therefore, these two loops are identical:
for item in &collection { /* item: &T */ }
for item in collection.iter() { /* item: &T */ }
Use &collection in for loops for brevity, and use .iter() when starting a method chain (collection.iter().filter(...).map(...)).
Double Reference in .iter().filter(...) (&&T)
Because .iter() produces items of type Item = &T, and .filter() passes a shared reference &Self::Item to its closure, a closure inside collection.iter().filter(...) receives a double reference (&&T). You can either dereference once with *, destructure with |&&x| (for Copy types), or compare against a reference:
fn main() {
let scores = [72, 88, 95, 64, 91];
// `scores.iter()` yields `&i32`; `.filter()` passes `&&i32` to the predicate:
let high_scores: Vec<i32> = scores
.iter()
.filter(|&&score| score >= 90)
.copied() // Converts `Iterator<Item = &i32>` -> `Iterator<Item = i32>`
.collect();
println!("High scores: {high_scores:?}");
}
High scores: [95, 91]
Converting Iterator<Item = &T> to Owned Values (.copied() and .cloned())
When an iterator yields &T from .iter() and you need owned T values downstream:
- Call
.copied()whenT: Copy(copies each&TintoTbitwise). - Call
.cloned()whenT: Clone(callsT::cloneon each&T).