Atualizado: 21/09/2025

Este conteúdo é original e não foi gerado por inteligência artificial.

Métodos da Stream API em Java: Filtragem, Mapeamento e Iteração

A Stream API oferece um conjunto de métodos para processar dados de forma declarativa. Entre as operações mais comuns estão a iteração, a filtragem e a transformação (mapeamento) dos elementos de um fluxo.

Iteração de Elementos: O Método forEach

Para percorrer os elementos de um stream e executar uma ação em cada um deles, é utilizado o método forEach. Esta é uma operação terminal, o que significa que ela consome o stream e encerra o pipeline de operações. O método forEach recebe como parâmetro um objeto Consumer, que define a ação a ser executada para cada elemento.

Por exemplo, para imprimir cada string de um stream no console:

import java.util.stream.Stream;

// ...

Stream<String> citiesStream = Stream.of("Paris", "London", "Madrid", "Berlin", "Brussels");
citiesStream.forEach(s -> System.out.println(s));

É possível simplificar esta chamada utilizando uma referência de método (Method Reference), que é uma forma compacta de uma expressão lambda que apenas chama um método existente.

Stream<String> citiesStream = Stream.of("Paris", "London", "Madrid", "Berlin", "Brussels");
citiesStream.forEach(System.out::println);

Filtragem de Elementos: O Método filter

A filtragem de elementos em um stream é realizada com o método filter, uma operação intermediária. Ele recebe como parâmetro um Predicate<T>, que é uma função que retorna true ou false para um elemento. O método filter então retorna um novo stream contendo apenas os elementos para os quais a condição foi avaliada como true.

Stream<String> citiesStream = Stream.of("Paris", "London", "Madrid", "Berlin", "Brussels");
citiesStream.filter(s -> s.length() == 6)
            .forEach(System.out::println);

Aqui, apenas as strings com exatamente 6 caracteres passarão pelo filtro, resultando na seguinte saída:

London
Madrid
Berlin

Transformação de Elementos: O Método map

O mapeamento é uma operação que converte cada elemento de um stream em outro objeto. Para isso, utiliza-se o método map, que é uma operação intermediária. A característica chave do map é que ele realiza uma transformação um-para-um: para cada elemento de entrada, ele produz exatamente um elemento de saída, embora o tipo do elemento possa mudar.

Ele recebe uma Function que define como transformar um elemento de tipo T em um elemento de tipo R, retornando um novo Stream<R>.

Por exemplo, podemos transformar um Stream<Phone> em um Stream<String> contendo apenas os nomes dos telefones.

// Supondo que a classe Phone já foi definida
Stream<Phone> phoneStream = Stream.of(
    new Phone("iPhone 16", 54000),
    new Phone("Lumia 950", 45000),
    new Phone("Samsung Galaxy S 24", 40000)
);

phoneStream.map(p -> p.getName()) // Transforma o fluxo de Phone para um fluxo de String
           .forEach(s -> System.out.println(s));

Para otimizar o processo ao transformar objetos em tipos primitivos, a Stream API oferece métodos especializados como mapToInt(), mapToLong() e mapToDouble().

iPhone 16
Lumia 950
Samsung Galaxy S 24

Mapeamento Plano: O Método flatMap

Enquanto map realiza uma transformação um-para-um, o flatMap é projetado para cenários um-para-muitos. Ele é utilizado quando uma operação de transformação sobre um elemento resulta não em um único novo elemento, mas em uma sequência (ou seja, em um novo stream) de elementos.

O flatMap funciona em duas etapas: primeiro, ele aplica uma função a cada elemento, que deve retornar um stream de novos elementos; segundo, ele "achata" (do inglês flattens) todos os streams gerados em um único fluxo contínuo.

Imagine que, para cada telefone, desejamos gerar duas strings: uma com o preço normal e outra com desconto. O flatMap é perfeito para isso.

// Supondo que a classe Phone já foi definida
Stream<Phone> phoneStream = Stream.of(
    new Phone("iPhone 16", 54000),
    new Phone("Lumia 950", 45000)
);

phoneStream.flatMap(p -> Stream.of(
                String.format("Modelo: %s, Preço normal: %d", p.getName(), p.getPrice()),
                String.format("Modelo: %s, Preço com desconto: %d", p.getName(), (int)(p.getPrice() * 0.9))
            ))
           .forEach(s -> System.out.println(s));

Para cada objeto Phone, a lambda cria um novo Stream contendo duas strings. O flatMap une esses pequenos streams em um único fluxo de saída.

Modelo: iPhone 16, Preço normal: 54000
Modelo: iPhone 16, Preço com desconto: 48600
Modelo: Lumia 950, Preço normal: 45000
Modelo: Lumia 950, Preço com desconto: 40500

Exemplo Completo e Prático

Para consolidar os conceitos, o código abaixo define a classe Phone e utiliza um pipeline de streams para filtrar e transformar os dados em um método main executável.

import java.util.stream.Stream;

class Phone {
    private String name;
    private int price;

    public Phone(String name, int price) {
        this.name = name;
        this.price = price;
    }

    public String getName() { return name; }
    public int getPrice() { return price; }
}

public class StreamExample {
    public static void main(String[] args) {
        Stream.of(
            new Phone("iPhone 16", 54000),
            new Phone("Lumia 950", 45000),
            new Phone("Samsung Galaxy S 24", 40000),
            new Phone("LG G4", 32000)
        )
        .filter(p -> p.getPrice() < 50000) // 1. Filtra telefones com preço abaixo de 50000
        .map(p -> p.getName())             // 2. Mapeia para obter apenas o nome
        .forEach(System.out::println);     // 3. Imprime cada nome no console
    }
}
Lumia 950
Samsung Galaxy S 24
LG G4

Resumo

  • forEach: É uma operação terminal usada para executar uma ação em cada elemento de um stream.
  • filter: É uma operação intermediária que retorna um novo stream contendo apenas os elementos que satisfazem uma condição.
  • map: É uma operação intermediária para transformações um-para-um, convertendo cada elemento em um novo elemento.
  • flatMap: É uma operação intermediária para transformações um-para-muitos, convertendo cada elemento em um stream de novos elementos e unificando os resultados em um único fluxo.
Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com