Iterators

collect()

The .collect() consumer drives an iterator to completion and gathers its elements into any target type B that implements the FromIterator<Self::Item> trait.

Signature and Type Inference

fn collect<B: FromIterator<Self::Item>>(self) -> B
where
    Self: Sized,

Because .collect() is generic over its return type B, the compiler almost always needs either a type annotation on the variable or turbofish syntax (.collect::<B>()) to know which FromIterator implementation to invoke. You can use _ inside the container type (Vec<_>, HashMap<_, _>) to let the compiler infer the element types:

use std::collections::{BTreeSet, HashMap};

fn main() {
    // 1. Variable type annotation with inferred element type `Vec<_>`:
    let squares: Vec<_> = (1..=4).map(|x| x * x).collect();

    // 2. Turbofish syntax `.collect::<BTreeSet<_>>()`:
    let unique = [3, 1, 2, 3, 1].into_iter().collect::<BTreeSet<_>>();

    // 3. Collecting `(K, V)` tuples into a `HashMap`:
    let pairs = [("http", 80_u16), ("https", 443)];
    let map: HashMap<_, _> = pairs.into_iter().collect();

    println!("Vec:      {squares:?}");
    println!("BTreeSet: {unique:?}");
    println!("HashMap:  {map:?}");
}
Vec:      [1, 4, 9, 16]
BTreeSet: {1, 2, 3}
HashMap:  {"http": 80, "https": 443}

Non-Collection FromIterator Targets (String and Result)

FromIterator is implemented for several types beyond standard collection containers:

Target Type B Required Iterator::Item Behavior of .collect::<B>()
Vec<T>, VecDeque<T>, HashSet<T> T Builds container from yielded items
HashMap<K, V>, BTreeMap<K, V> (K, V) Inserts each key-value tuple
String char, &char, &str, String, Cow<'_, str> Concatenates characters or string slices into a single String
Result<C, E> (where C: FromIterator<T>) Result<T, E> Short-circuits on the first Err(e); otherwise returns Ok(C)
Option<C> (where C: FromIterator<T>) Option<T> Short-circuits on the first None; otherwise returns Some(C)

Short-Circuiting Iterator<Item = Result<T, E>> into Result<Vec<T>, E>

Collecting an iterator of Result<T, E> into Result<Vec<T>, E> stops polling the iterator at the first Err(e) without evaluating remaining elements:

fn parse_all(inputs: &[&str]) -> Result<Vec<i32>, std::num::ParseIntError> {
    inputs.iter().map(|s| s.parse::<i32>()).collect()
}

fn main() {
    println!("All valid: {:?}", parse_all(&["10", "20", "30"]));
    println!("Has error: {:?}", parse_all(&["10", "oops", "30"]));
}
All valid: Ok([10, 20, 30])
Has error: Err(ParseIntError { kind: InvalidDigit })