---
title: "Iterator Trait em Rust"
url: "https://rustlang.com.br/stdlib/iterator/"
markdown_url: "https://rustlang.com.br/stdlib/iterator.MD"
description: "Guia completo do trait Iterator em Rust: map, filter, fold, collect, enumerate, zip, chain e criação de iteradores customizados."
date: "2026-02-23"
author: "Equipe Rust Brasil"
---

# Iterator Trait em Rust

Guia completo do trait Iterator em Rust: map, filter, fold, collect, enumerate, zip, chain e criação de iteradores customizados.


## O que é o Trait Iterator

O trait `Iterator` é a base da programação funcional e do processamento de coleções em Rust. Qualquer tipo que implemente `Iterator` precisa definir apenas um método: `next()`, que retorna `Option<Self::Item>` — `Some(valor)` para o próximo elemento ou `None` quando a iteração termina. A partir disso, dezenas de métodos adaptadores ficam disponíveis automaticamente.

Iteradores em Rust são **preguiçosos** (lazy): adaptadores como `map` e `filter` não fazem nada até que um **consumidor** como `collect`, `for_each`, `sum` ou `fold` solicite os valores. Essa abordagem elimina alocações intermediárias e permite ao compilador otimizar cadeias inteiras de transformações em loops eficientes — frequentemente com desempenho igual ou superior ao de loops manuais.

---

## Métodos Mais Usados

```rust
fn main() {
    let numeros = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    // iter() - referências imutáveis
    // into_iter() - consome a coleção
    // iter_mut() - referências mutáveis

    // Demonstração básica com next()
    let mut iter = numeros.iter();
    assert_eq!(iter.next(), Some(&1));
    assert_eq!(iter.next(), Some(&2));

    println!("{numeros:?}"); // numeros ainda existe (iter() empresta)
}
```

---

## Tabela de Métodos Principais

### Adaptadores (preguiçosos — retornam outro iterador)

| Método | Descrição | Exemplo |
|---|---|---|
| `map(f)` | Transforma cada elemento | `.map(\|x\| x * 2)` |
| `filter(f)` | Mantém elementos onde `f` é true | `.filter(\|x\| **x > 3)` |
| `filter_map(f)` | map + filter (descarta None) | `.filter_map(\|x\| x.parse().ok())` |
| `flat_map(f)` | map + flatten | `.flat_map(\|x\| vec![x, x*10])` |
| `flatten()` | Achata iterador de iteradores | `vec![vec![1,2], vec![3]].into_iter().flatten()` |
| `enumerate()` | Adiciona índice `(i, val)` | `.enumerate()` |
| `zip(outro)` | Combina dois iteradores em tuplas | `.zip(outro_iter)` |
| `chain(outro)` | Concatena dois iteradores | `.chain(outro_iter)` |
| `take(n)` | Pega os primeiros `n` | `.take(5)` |
| `skip(n)` | Pula os primeiros `n` | `.skip(2)` |
| `take_while(f)` | Pega enquanto `f` for true | `.take_while(\|x\| **x < 5)` |
| `skip_while(f)` | Pula enquanto `f` for true | `.skip_while(\|x\| **x < 5)` |
| `peekable()` | Permite espiar o próximo sem consumir | `.peekable()` |
| `rev()` | Inverte (requer `DoubleEndedIterator`) | `.rev()` |
| `cloned()` | Clona referências `&T` → `T` | `.cloned()` |
| `copied()` | Copia referências `&T` → `T` (Copy) | `.copied()` |
| `inspect(f)` | Executa side-effect sem alterar | `.inspect(\|x\| println!("{x}"))` |
| `step_by(n)` | Avança `n` a cada iteração | `.step_by(2)` |

### Consumidores (executam a iteração)

| Método | Descrição | Exemplo |
|---|---|---|
| `collect()` | Coleta em uma coleção | `.collect::<Vec<_>>()` |
| `for_each(f)` | Executa `f` para cada elemento | `.for_each(\|x\| println!("{x}"))` |
| `fold(init, f)` | Reduz a um único valor | `.fold(0, \|acc, x\| acc + x)` |
| `reduce(f)` | Como fold, sem valor inicial | `.reduce(\|a, b\| a + b)` |
| `sum()` | Soma todos os elementos | `.sum::<i32>()` |
| `product()` | Produto de todos os elementos | `.product::<i32>()` |
| `count()` | Conta os elementos | `.count()` |
| `any(f)` | Algum satisfaz `f`? | `.any(\|x\| *x > 5)` |
| `all(f)` | Todos satisfazem `f`? | `.all(\|x\| *x > 0)` |
| `find(f)` | Primeiro que satisfaz `f` | `.find(\|x\| **x > 5)` → `Option` |
| `position(f)` | Índice do primeiro que satisfaz `f` | `.position(\|x\| *x > 5)` → `Option` |
| `min()` / `max()` | Menor / maior elemento | `.max()` → `Option` |
| `min_by_key(f)` | Menor por critério | `.min_by_key(\|x\| x.abs())` |
| `last()` | Último elemento | `.last()` → `Option` |
| `nth(n)` | N-ésimo elemento | `.nth(3)` → `Option` |
| `unzip()` | Separa tuplas em duas coleções | `.unzip::<Vec<_>, Vec<_>>()` |

---

## Exemplos Práticos

### 1. Pipeline de Transformação de Dados

```rust
#[derive(Debug)]
struct Venda {
    produto: String,
    valor: f64,
    quantidade: u32,
}

fn main() {
    let vendas = vec![
        Venda { produto: "Notebook".into(), valor: 3500.0, quantidade: 2 },
        Venda { produto: "Mouse".into(), valor: 89.90, quantidade: 15 },
        Venda { produto: "Teclado".into(), valor: 199.90, quantidade: 8 },
        Venda { produto: "Monitor".into(), valor: 1200.0, quantidade: 3 },
        Venda { produto: "Webcam".into(), valor: 149.90, quantidade: 5 },
    ];

    // Total de vendas acima de R$ 1000 em receita
    let total_alto_valor: f64 = vendas
        .iter()
        .map(|v| v.valor * v.quantidade as f64)
        .filter(|&receita| receita > 1000.0)
        .sum();
    println!("Receita alto valor: R$ {total_alto_valor:.2}");

    // Top 3 produtos por receita
    let mut por_receita: Vec<_> = vendas
        .iter()
        .map(|v| (&v.produto, v.valor * v.quantidade as f64))
        .collect();
    por_receita.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());

    println!("\nTop 3 por receita:");
    for (produto, receita) in por_receita.iter().take(3) {
        println!("  {produto}: R$ {receita:.2}");
    }
}
```

### 2. Criando um Iterador Customizado

```rust
struct Fibonacci {
    a: u64,
    b: u64,
}

impl Fibonacci {
    fn new() -> Self {
        Fibonacci { a: 0, b: 1 }
    }
}

impl Iterator for Fibonacci {
    type Item = u64;

    fn next(&mut self) -> Option<Self::Item> {
        let resultado = self.a;
        let novo = self.a.checked_add(self.b)?; // None se houver overflow
        self.a = self.b;
        self.b = novo;
        Some(resultado)
    }
}

fn main() {
    // Primeiros 15 números de Fibonacci
    let primeiros: Vec<u64> = Fibonacci::new().take(15).collect();
    println!("Fibonacci: {primeiros:?}");

    // Fibonacci menores que 1000
    let menores: Vec<u64> = Fibonacci::new()
        .take_while(|&n| n < 1000)
        .collect();
    println!("Menores que 1000: {menores:?}");

    // Soma dos pares de Fibonacci até 4 milhões
    let soma_pares: u64 = Fibonacci::new()
        .take_while(|&n| n <= 4_000_000)
        .filter(|n| n % 2 == 0)
        .sum();
    println!("Soma dos pares até 4M: {soma_pares}");
}
```

### 3. enumerate, zip e chain

```rust
fn main() {
    let linguagens = vec!["Rust", "Python", "Go", "TypeScript"];
    let notas = vec![10, 8, 7, 9];

    // enumerate — índice + valor
    println!("Rankings:");
    for (i, lang) in linguagens.iter().enumerate() {
        println!("  {}. {lang}", i + 1);
    }

    // zip — combinar dois iteradores
    println!("\nNotas:");
    for (lang, nota) in linguagens.iter().zip(notas.iter()) {
        println!("  {lang}: {nota}/10");
    }

    // chain — concatenar iteradores
    let frontend = vec!["React", "Vue"];
    let backend = vec!["Actix", "Axum"];
    let todos: Vec<&str> = frontend.iter().copied()
        .chain(backend.iter().copied())
        .collect();
    println!("\nFrameworks: {todos:?}");

    // unzip — separar tuplas
    let pares = vec![(1, "um"), (2, "dois"), (3, "três")];
    let (numeros, nomes): (Vec<i32>, Vec<&str>) = pares.into_iter().unzip();
    println!("\nNúmeros: {numeros:?}");
    println!("Nomes: {nomes:?}");
}
```

### 4. fold para Agregações Complexas

```rust
fn main() {
    let transacoes = vec![100.0, -50.0, 200.0, -30.0, -80.0, 150.0];

    // Calcular saldo, total de créditos e débitos em uma passada
    let (saldo, creditos, debitos) = transacoes.iter().fold(
        (0.0_f64, 0.0_f64, 0.0_f64),
        |(saldo, cred, deb), &valor| {
            if valor >= 0.0 {
                (saldo + valor, cred + valor, deb)
            } else {
                (saldo + valor, cred, deb + valor.abs())
            }
        },
    );

    println!("Saldo: R$ {saldo:.2}");
    println!("Total créditos: R$ {creditos:.2}");
    println!("Total débitos: R$ {debitos:.2}");

    // Construir uma string formatada com fold
    let palavras = vec!["Rust", "é", "incrível"];
    let frase = palavras.iter().enumerate().fold(
        String::new(),
        |mut acc, (i, palavra)| {
            if i > 0 {
                acc.push(' ');
            }
            acc.push_str(palavra);
            acc
        },
    );
    println!("{frase}");
}
```

### 5. windows e chunks para Processamento em Blocos

```rust
fn main() {
    let precos = vec![100.0, 102.0, 98.0, 105.0, 110.0, 108.0, 115.0, 112.0];

    // Média móvel de 3 períodos usando windows
    let medias_moveis: Vec<f64> = precos
        .windows(3)
        .map(|janela| janela.iter().sum::<f64>() / janela.len() as f64)
        .collect();
    println!("Médias móveis: {medias_moveis:.1?}");

    // Variação percentual entre dias consecutivos
    let variacoes: Vec<f64> = precos
        .windows(2)
        .map(|par| ((par[1] - par[0]) / par[0]) * 100.0)
        .collect();
    println!("Variações: {variacoes:.2?}%");

    // Processar dados em lotes de 3
    let dados: Vec<i32> = (1..=12).collect();
    let lotes: Vec<Vec<i32>> = dados
        .chunks(3)
        .map(|chunk| chunk.to_vec())
        .collect();
    println!("Lotes de 3: {lotes:?}");
}
```

---

## Dicas de Performance e Armadilhas

1. **Iteradores são zero-cost**: O compilador otimiza cadeias de iteradores para loops simples. Não há alocação intermediária entre `map`, `filter`, etc. Use sem medo.

2. **`collect()` precisa de tipo**: O compilador nem sempre consegue inferir o tipo destino. Use turbofish: `.collect::<Vec<_>>()` ou anote a variável: `let v: Vec<_> = ...`.

3. **`iter()` vs `into_iter()`**: `iter()` empresta a coleção (retorna `&T`), `into_iter()` consome (retorna `T`). Se precisar dos valores, use `into_iter()` ou `.iter().copied()` para tipos `Copy`.

4. **Cuidado com `filter` em referências**: O predicado de `filter` recebe `&&T` quando usado com `iter()`. Use `|&&x|` ou `|x| **x > 5` para desreferenciar.

5. **`for_each` vs `for`**: Ambos são equivalentes em performance. Use `for_each` em cadeias de iteradores; use `for` quando precisar de `break`, `continue` ou `return`.

6. **`peekable()` para look-ahead**: Quando precisar decidir com base no próximo elemento sem consumi-lo, use `.peekable()` e o método `peek()`.

---

## Veja Também

- [Iterar Coleções em Rust](/receitas/iterar-colecoes/) — receitas práticas de iteração
- [Iteradores em Rust](/artigos/iteradores-rust/) — artigo aprofundado sobre o sistema de iteradores
- [Vec\<T\>: Vetor Dinâmico](/stdlib/vec/) — a coleção mais iterada
- [HashMap\<K,V\>](/stdlib/hashmap/) — iteração sobre pares chave-valor
- [Option\<T\>](/stdlib/option/) — `next()` retorna Option
- [Slices (&[T])](/stdlib/slice/) — windows, chunks e iteração sobre fatias
- [Cheatsheet Rust](/cheatsheet/) — referência rápida de sintaxe
- [Documentação oficial — std::iter::Iterator](https://doc.rust-lang.org/std/iter/trait.Iterator.html)
