Atualizado: 21/09/2025

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

Criação de Streams em Java

Existem diversas maneiras de criar um stream de dados, utilizando diferentes fontes. As fontes mais comuns são coleções e arrays.

A Partir de Coleções

A forma mais comum de criar um stream é a partir de uma coleção existente. A partir do JDK 8, a interface Collection, que é a base para todas as coleções padrão (como ArrayList, HashSet, etc.), foi aprimorada com dois métodos para gerar streams:

  • default Stream<E> stream(): Retorna um stream sequencial dos elementos da coleção.
  • default Stream<E> parallelStream(): Retorna um stream paralelo, que pode processar os dados em múltiplos núcleos de processador para melhorar o desempenho em operações complexas.

Considere um exemplo utilizando um ArrayList.

import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Stream;

public class Program {
    public static void main(String[] args) {
        ArrayList<String> cities = new ArrayList<>();
        Collections.addAll(cities, "Paris", "Londres", "Madrid");

        cities.stream() // Obtém o stream a partir da lista
              .filter(s -> s.length() == 6) // Aplica uma filtragem por tamanho da string
              .forEach(s -> System.out.println(s)); // Imprime os resultados no console
    }
}

No exemplo acima, a chamada cities.stream() cria um fluxo de dados a partir da lista cities. Em seguida, as operações são encadeadas de forma fluente.

É importante entender que cada operação intermediária, como filter, retorna um novo stream modificado. Embora o encadeamento seja a prática mais comum, o código poderia ser escrito de forma mais verbosa para ilustrar esse conceito.

ArrayList<String> cities = new ArrayList<>();
Collections.addAll(cities, "Paris", "Londres", "Madrid");

// Passo 1: Obter o stream inicial
Stream<String> citiesStream = cities.stream();

// Passo 2: Aplicar uma operação intermediária, que retorna um novo stream
Stream<String> filteredStream = citiesStream.filter(s -> s.length() == 6);

// Passo 3: Aplicar uma operação terminal no stream resultante
filteredStream.forEach(s -> System.out.println(s));

O Ciclo de Vida e o Consumo Único de um Stream

Um stream passa por três estágios em seu ciclo de vida:

  1. Criação: O stream é gerado a partir de uma fonte de dados.
  2. Operações Intermediárias: Uma ou mais operações são aplicadas para transformar o stream.
  3. Operação Terminal: Uma operação final é aplicada para produzir um resultado e consumir o stream.

Um conceito fundamental é que um stream só pode ser consumido uma vez. Após a chamada de uma operação terminal (como forEach ou count), o stream é considerado "fechado" e não pode ser reutilizado. Tentar chamar outra operação no mesmo stream resultará em uma exceção IllegalStateException.

Stream<String> citiesStream = Stream.of("Paris", "Londres", "Madrid");

// A primeira operação terminal consome o stream com sucesso
citiesStream.forEach(s -> System.out.println(s));

// Esta linha causará um erro em tempo de execução (IllegalStateException)
// porque o stream já foi consumido pela operação forEach.
long number = citiesStream.count();

Para realizar múltiplas operações terminais, é necessário criar um novo stream a partir da fonte de dados original para cada operação.

A Partir de Arrays

A classe de utilitários Arrays fornece o método stream() para criar um stream a partir de um array.

import java.util.Arrays;
import java.util.stream.Stream;

// ...

String[] cityArray = {"Paris", "Londres", "Madrid"};
Stream<String> citiesStream = Arrays.stream(cityArray);
citiesStream.forEach(s -> System.out.println(s));

Existem também sobrecargas desse método para criar streams de tipos primitivos, o que é mais eficiente do que usar um Stream<Integer> ou Stream<Double>, pois evita o boxing/unboxing.

import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.DoubleStream;

// ...

int[] numbers = {1, 2, 4, 5, 7};
IntStream intStream = Arrays.stream(numbers);
intStream.forEach(i -> System.out.println(i));

long[] longNumbers = {100L, 250L, 400L, 5843787L, 237L};
LongStream longStream = Arrays.stream(longNumbers);
longStream.forEach(l -> System.out.println(l));

double[] doubleNumbers = {3.4, 6.7, 9.5, 8.2345, 121.0};
DoubleStream doubleStream = Arrays.stream(doubleNumbers);
doubleStream.forEach(d -> System.out.println(d));

Com Métodos Estáticos (Stream.of)

Outra maneira flexível de criar streams é usar o método estático of(), disponível nas interfaces Stream, IntStream, LongStream e DoubleStream. Este método permite criar um stream diretamente a partir de um conjunto de valores.

import java.util.stream.Stream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.DoubleStream;

// ...

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

// Também é possível passar um array para o método of()
String[] citiesArray = {"Paris", "Londres", "Madrid"};
Stream<String> citiesStream2 = Stream.of(citiesArray);

// Usando os métodos of() para tipos primitivos
IntStream intStream = IntStream.of(1, 2, 4, 5, 7);
intStream.forEach(i -> System.out.println(i));

LongStream longStream = LongStream.of(100L, 250L, 400L, 5843787L, 237L);
longStream.forEach(l -> System.out.println(l));

DoubleStream doubleStream = DoubleStream.of(3.4, 6.7, 9.5, 8.2345, 121.0);
doubleStream.forEach(d -> System.out.println(d));

Resumo

  • A partir de Coleções: O método minhaColecao.stream() é a forma mais comum de criar um stream. parallelStream() é usado para processamento paralelo.
  • A partir de Arrays: O método estático Arrays.stream(meuArray) cria um stream a partir de um array, com versões otimizadas para tipos primitivos.
  • A partir de Valores: O método estático Stream.of("a", "b", "c") cria um stream diretamente a partir de uma sequência de elementos.
  • Consumo Único: Um stream só pode ser usado uma vez. Após a execução de uma operação terminal, ele é fechado e não pode ser reutilizado.
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