Carregando...

Streams em Java

Streams em Java são uma poderosa abstração introduzida a partir da versão 8 da linguagem, projetada para simplificar o processamento de coleções e fluxos de dados de forma funcional e eficiente. Ao utilizar streams, desenvolvedores podem aplicar operações complexas, como filtragem, mapeamento, ordenação e agregação de dados, sem a necessidade de escrever loops explícitos, resultando em código mais conciso, legível e menos propenso a erros.
No contexto de desenvolvimento de software e arquitetura de sistemas, streams permitem processamentos paralelos, análise de grandes volumes de dados, manipulação de logs, cálculos estatísticos e integração com APIs reativas. Eles se integram perfeitamente aos princípios de programação orientada a objetos, permitindo que dados encapsulados em objetos sejam processados de maneira elegante e eficiente.
Conceitos-chave incluem:

  • Sintaxe: criação de streams com stream() ou parallelStream(), operações intermediárias como filter, map e operações finais como collect.
  • Estruturas de dados: List, Set, Map (através de entrySet()), Arrays e outras coleções iteráveis.
  • Algoritmos: ordenação, busca, agregações e cálculos estatísticos otimizados.
  • Princípios OOP: streams trabalham diretamente com objetos e métodos, promovendo encapsulamento e modularidade.
    Neste tutorial, o leitor aprenderá a criar streams, aplicar transformações, realizar agregações, manipular objetos complexos e implementar boas práticas para desempenho, tratamento de erros e manutenção de código.

Exemplo Básico

java
JAVA Code
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class ExemploBasico {
public static void main(String\[] args) {
List<Integer> numeros = Arrays.asList(1, 2, 3, 4, 5, 6);

// Filtrar números pares e calcular seu quadrado
List<Integer> quadradosPares = numeros.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * n)
.collect(Collectors.toList());

System.out.println("Quadrados dos números pares: " + quadradosPares);
}

}

Neste exemplo, uma lista de números é criada e transformada em um stream com stream(). A operação intermediária filter seleciona apenas os números pares, enquanto map calcula o quadrado de cada número selecionado. Por fim, collect(Collectors.toList()) agrega os resultados em uma nova lista.
Esse exemplo demonstra conceitos centrais de streams: criação de fluxo, operações intermediárias (filter e map) e operação final (collect). Utilizar streams elimina a necessidade de loops explícitos, resultando em código mais limpo, legível e menos sujeito a erros lógicos. Em aplicações práticas, isso é útil para processamento de dados em batch, análises estatísticas e manipulação de coleções grandes.

Exemplo Prático

java
JAVA Code
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class ExemploAvancado {
static class Funcionario {
String nome;
int idade;
double salario;

Funcionario(String nome, int idade, double salario) {
this.nome = nome;
this.idade = idade;
this.salario = salario;
}

public String getNome() { return nome; }
public int getIdade() { return idade; }
public double getSalario() { return salario; }
}

public static void main(String[] args) {
List<Funcionario> funcionarios = Arrays.asList(
new Funcionario("Ana", 28, 5000),
new Funcionario("Bruno", 34, 7000),
new Funcionario("Carla", 22, 3000),
new Funcionario("Daniel", 29, 6000)
);

// Encontrar o funcionário com maior salário acima de 25 anos
Optional<Funcionario> maiorSalario = funcionarios.stream()
.filter(f -> f.getIdade() > 25)
.max((f1, f2) -> Double.compare(f1.getSalario(), f2.getSalario()));

maiorSalario.ifPresent(f -> System.out.println("Maior salário acima de 25 anos: " + f.getNome() + " Salário: " + f.getSalario()));
}

}

Neste exemplo avançado, uma lista de objetos Funcionario é processada usando streams. A operação filter seleciona funcionários com idade acima de 25 anos, enquanto max identifica o funcionário com maior salário. O resultado é encapsulado em um Optional para evitar erros caso nenhum elemento satisfaça o filtro.
Esse exemplo demonstra a integração de streams com princípios OOP, permitindo manipulação de objetos complexos de maneira funcional e eficiente. Em cenários reais, é útil para relatórios, análises financeiras e processamento de dados de recursos humanos. Streams substituem loops aninhados, melhoram legibilidade e diminuem riscos de vazamento de memória ou erros de lógica.

Boas práticas e erros comuns:

  1. Boas práticas:
    * Encadear operações intermediárias de forma clara e legível.
    * Usar Optional para valores que podem não existir.
    * Para coleções grandes, considerar parallelStream() garantindo que objetos sejam thread-safe.
    * Evitar múltiplas traversadas do stream desnecessariamente.
  2. Erros comuns:
    * Uso excessivo de operações intermediárias, prejudicando performance.
    * Ignorar tratamento de exceções em streams que envolvem I/O ou banco de dados.
    * Manter objetos grandes em memória durante o processamento do stream.
    * Uso inadequado de parallelStream() em pequenas coleções, afetando desempenho.
    Dicas de depuração incluem o uso de peek() para inspecionar elementos intermediários. Otimização envolve escolher a estrutura de dados correta e eliminar operações redundantes. Evite modificar estado compartilhado dentro do stream para manter segurança e consistência.

📊 Tabela de Referência

Element/Concept Description Usage Example
stream() Cria um fluxo a partir de uma coleção List<Integer> nums = list.stream().collect(Collectors.toList());
filter() Seleciona elementos baseado em condição numeros.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());
map() Transforma elementos do fluxo numeros.stream().map(n -> n * n).collect(Collectors.toList());
collect() Agrega os elementos em uma coleção numeros.stream().map(n -> n * n).collect(Collectors.toList());
Optional Representa um valor que pode ou não existir Optional<Funcionario> f = list.stream().findFirst();

Resumo e próximos passos:
Após dominar streams em Java, o leitor será capaz de criar fluxos, aplicar filtros, transformações e agregações, além de manipular objetos complexos de forma funcional e orientada a objetos. Streams aumentam legibilidade, manutenção e eficiência de sistemas backend e suportam lógica de negócio complexa em arquiteturas escaláveis.
Próximos tópicos incluem parallelStream(), streams infinitos e coletores customizados. Exercícios de análise de dados, processamento de logs e geração de relatórios consolidarão habilidades. Documentação oficial do Java, tutoriais avançados e prática contínua são recursos essenciais para aperfeiçoar o uso de streams em aplicações backend.

🧠 Teste Seu Conhecimento

Pronto para Começar

Teste seu Conhecimento

Teste sua compreensão deste tópico com questões práticas.

4
Perguntas
🎯
70%
Para Passar
♾️
Tempo
🔄
Tentativas

📝 Instruções

  • Leia cada pergunta cuidadosamente
  • Selecione a melhor resposta para cada pergunta
  • Você pode refazer o quiz quantas vezes quiser
  • Seu progresso será mostrado no topo