Skip to content

Instantly share code, notes, and snippets.

@lrlucena
Created January 23, 2025 12:10
Show Gist options
  • Save lrlucena/0934c1a68a82cb55e88168c618a539ba to your computer and use it in GitHub Desktop.
Save lrlucena/0934c1a68a82cb55e88168c618a539ba to your computer and use it in GitHub Desktop.

Tutorial: Java Streams

1. Introdução ao Java Streams

Explicação: Java Streams é uma API introduzida no Java 8 para processar coleções de dados de forma declarativa e funcional. Ela permite operações como filtragem, mapeamento, ordenação e redução de dados de maneira eficiente.

Características principais:

  • Não altera a coleção original: Streams operam sobre uma cópia dos dados.
  • Operações intermediárias e terminais: As operações intermediárias (como filter e map) são lazy, ou seja, só são executadas quando uma operação terminal (como collect ou forEach) é chamada.
  • Programação funcional: Utiliza expressões lambda para simplificar o código.

Exemplo básico:

List<String> nomes = Arrays.asList("Ana", "João", "Maria", "Pedro");
nomes.stream()
     .filter(nome -> nome.startsWith("A"))
     .forEach(System.out::println);
// Saída: Ana

Exercício 1: Crie uma lista de números inteiros e use Streams para imprimir apenas os números pares.


2. Operações Intermediárias

Explicação: Operações intermediárias transformam ou filtram os dados, mas não executam o processamento até que uma operação terminal seja chamada.

Principais operações intermediárias:

  • filter(Predicate<T>): Filtra elementos com base em uma condição.
  • map(Function<T, R>): Transforma cada elemento em outro tipo de dado.
  • sorted(): Ordena os elementos.
  • distinct(): Remove elementos duplicados.

Exemplo:

List<Integer> numeros = Arrays.asList(1, 2, 3, 4, 5, 6);
numeros.stream()
       .filter(n -> n % 2 == 0) // Filtra pares
       .map(n -> n * 2)         // Multiplica por 2
       .forEach(System.out::println);
// Saída: 4, 8, 12

Exercício 2: Dada uma lista de strings, use filter para encontrar palavras com mais de 5 caracteres e map para convertê-las em maiúsculas.


3. Operações Terminais

Explicação: Operações terminais produzem um resultado final ou um efeito colateral, como imprimir valores ou coletar dados em uma nova coleção.

Principais operações terminais:

  • forEach(Consumer<T>): Executa uma ação para cada elemento.
  • collect(Collector<T>): Coleta os elementos em uma coleção.
  • reduce(): Combina os elementos em um único valor.
  • count(): Retorna a quantidade de elementos.

Exemplo:

List<String> palavras = Arrays.asList("java", "stream", "api", "exemplo");
long count = palavras.stream()
                    .filter(p -> p.length() > 3)
                    .count();
System.out.println("Quantidade: " + count);
// Saída: Quantidade: 3

Exercício 3: Crie uma lista de números e use reduce para calcular a soma de todos os elementos.


4. Coletando Resultados com collect

Explicação: O método collect é usado para transformar o Stream em uma coleção ou outro tipo de dado.

Exemplos comuns:

  • Collectors.toList(): Coleta os elementos em uma lista.
  • Collectors.toSet(): Coleta os elementos em um conjunto (sem duplicatas).
  • Collectors.joining(): Concatena strings.

Exemplo:

List<String> frutas = Arrays.asList("maçã", "banana", "laranja", "maçã");
Set<String> semDuplicatas = frutas.stream()
                                  .collect(Collectors.toSet());
System.out.println(semDuplicatas);
// Saída: [maçã, banana, laranja]

Exercício 4: Dada uma lista de nomes, use collect para criar uma única string com todos os nomes separados por vírgulas.


5. Streams de Tipos Primitivos

Explicação: Java Streams também suporta operações com tipos primitivos (int, long, double) através de classes como IntStream, LongStream e DoubleStream.

Exemplo:

IntStream.range(1, 6) // Cria um Stream de 1 a 5
         .forEach(System.out::println);
// Saída: 1, 2, 3, 4, 5

Exercício 5: Use IntStream para gerar os primeiros 10 números pares e imprimi-los.


6. Streams Paralelos

Explicação: Streams podem ser processados em paralelo para melhorar o desempenho em grandes volumes de dados. Basta usar o método parallelStream().

Exemplo:

List<Integer> numeros = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
numeros.parallelStream()
       .filter(n -> n % 2 == 0)
       .forEach(System.out::println);
// Saída: Números pares em ordem não determinística

Exercício 6: Crie uma lista de 1000 números aleatórios e use parallelStream para encontrar o maior número.


7. Exercícios Finais

  1. Dada uma lista de pessoas (nome e idade), use Streams para:
    • Filtrar pessoas com mais de 18 anos.
    • Mapear para uma lista de nomes.
    • Ordenar os nomes alfabeticamente.
  2. Crie um Stream de números inteiros e calcule a média dos números maiores que 50.
  3. Use Collectors.groupingBy para agrupar uma lista de palavras pelo seu tamanho.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment