Especialização em Sistemas com Java 21 LTS • Módulo de Recursos Avançados e Concorrência


🗺️ Mapa Conceitual do Tópico

flowchart TD
    subgraph FUNCIONAL["Pilares da Programação Funcional"]
        A["@FunctionalInterface (Método Abstrato Único)"]
        B["Expressões Lambda: (x, y) -> x + y"]
        C["Method References: String::toUpperCase"]
        A --> B & C
    end

    subgraph INTERFACES["Interfaces Funcionais Nativas (java.util.function)"]
        D["Predicate~T~: test(T) -> boolean"]
        E["Function~T, R~: apply(T) -> R"]
        F["Consumer~T~: accept(T) -> void"]
        G["Supplier~T~: get() -> T"]
    end

    subgraph STREAMS["Pipeline do Streams API"]
        H["Fonte de Dados (List, Set, Files)"]
        I["Operações Intermediárias (Lazy: filter, map, flatMap)"]
        J["Operações Terminais (Eager: collect, reduce, count)"]
        H --> I --> J
    end

    FUNCIONAL --> INTERFACES
    INTERFACES --> STREAMS

    style A fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px
    style D fill:#ede7f6,stroke:#7e57c2,stroke-width:2px
    style I fill:#fff3e0,stroke:#ff9800,stroke-width:2px
    style J fill:#e8f5e9,stroke:#4caf50,stroke-width:2px

🧬 1. Fundamentos da Programação Funcional no Java

Desde o Java 8 e amplamente refinado no Java 21 LTS, a linguagem incorporou capacidades declarativas e funcionais. Uma interface anotada com @FunctionalInterface é aquela que possui exatamente um método abstrato (SAM - Single Abstract Method), servindo de base para expressões lambda.

As Quatro Grandes Interfaces Funcionais (java.util.function):

  • Predicate<T>: Recebe um valor do tipo T e retorna um boolean primitivo (test(T)). Utilizado para filtros.
  • Function<T, R>: Recebe um argumento T e o transforma em um resultado R (apply(T)). Utilizado para mapeamentos e projeções.
  • Consumer<T>: Recebe um argumento T e não retorna nada (void accept(T)). Utilizado para efeitos colaterais (logs, escrita).
  • Supplier<T>: Não recebe parâmetros e produz um valor T (get()). Utilizado para fábricas e inicialização preguiçosa (lazy evaluation).

Method References (::):

Açúcar sintático para lambdas que apenas repassam parâmetros para um método pré-existente:

  • Método de Instância de Objeto Específico: System.out::println
  • Método Estático: Math::max
  • Construtor: ArrayList::new

🌊 2. A Arquitetura do Streams API

Uma Stream em Java é um wrapper funcional em torno de uma fonte de dados que permite computação declarativa encadeada.

Características Fundamentais:

  1. Não Armazena Dados: Uma Stream não é uma estrutura de dados; ela processa elementos sob demanda.
  2. Avaliação Preguiçosa (Lazy Evaluation): As operações intermediárias (filter, map, sorted, distinct, limit) não processam absolutamente nenhum dado no momento da invocação. O processamento real só é disparado quando uma operação terminal é executada.
  3. Fusão de Laços (Loop Fusion): Em vez de iterar sobre a lista inteira no filter e depois novamente no map, a JVM funde as etapas e processa cada elemento através de todo o pipeline sequencialmente em uma única passagem.

🧩 3. Agrupamentos e Agregações com Collectors

A classe utilitária java.util.stream.Collectors permite transformar fluxos de streams em mapas complexos, relatórios sumarizados e agrupamentos multi-nível:

// Agrupamento por Categoria com Cálculo de Faturamento Total
Map<Categoria, BigDecimal> faturamentoPorCategoria = vendas.stream()
    .collect(Collectors.groupingBy(
        Venda::getCategoria,
        Collectors.reducing(BigDecimal.ZERO, Venda::getValor, BigDecimal::add)
    ));

⚡ 4. Paralelismo com parallelStream() e ForkJoinPool

Ao invocar .parallelStream(), o Java divide automaticamente o conjunto de dados em sub-partições utilizando o framework ForkJoinPool.commonPool(), aproveitando todos os núcleos da CPU.

Quando NÃO usar Streams Paralelas:

  • Coleções pequenas (onde a sobrecarga de dividir tarefas e sincronizar threads supera o tempo de execução).
  • Operações que dependem de estado compartilhado mutável (provocam race conditions).
  • Operações de I/O bloqueante (travam as threads compartilhadas do commonPool).

📊 5. Matriz Comparativa: Laço Clássico (for) vs Streams API

Critério Laço Imperativo (for) Streams API Declarativa
Estilo de Programação Imperativo (foco no “como iterar”) Declarativo (foco no “o que transformar”)
Mutabilidade Manipula variáveis externas mutáveis Promove imutabilidade e funções puras
Legibilidade em Pipelines Sofre de aninhamento excessivo (nested loops) Fluente, linear e de fácil manutenção
Execução Paralela Exige controle manual de Threads/Locks Trivial com .parallelStream()
Overhead de Alocação Zero (opera sobre ponteiros locais) Mínimo (criação de objetos de pipeline)

💻 6. Código de Demonstração Corporativo (Java 21 LTS)

package com.empresa.funcional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Pipeline corporativo de Business Intelligence (BI) de vendas com Streams API.
 */
public class AnalisadorVendasBi {

    public enum CanalVenda { ECOMMERCE, LOJA_FISICA, CORPORATIVO_B2B }

    public record Venda(String id, String vendedor, CanalVenda canal, BigDecimal total, boolean aprovada) {}

    public static void main(String[] args) {
        System.out.println("================================================================================");
        System.out.println("            PIPELINE DE BI DE VENDAS COM JAVA 21 STREAMS API                    ");
        System.out.println("================================================================================");

        List<Venda> historicoVendas = List.of(
            new Venda("V01", "Carla Dias", CanalVenda.ECOMMERCE, new BigDecimal("1250.00"), true),
            new Venda("V02", "Renato Abreu", CanalVenda.LOJA_FISICA, new BigDecimal("450.00"), false), // Não aprovada
            new Venda("V03", "Carla Dias", CanalVenda.ECOMMERCE, new BigDecimal("3200.00"), true),
            new Venda("V04", "Felipe Melo", CanalVenda.CORPORATIVO_B2B, new BigDecimal("45000.00"), true),
            new Venda("V05", "Renato Abreu", CanalVenda.LOJA_FISICA, new BigDecimal("1800.00"), true),
            new Venda("V06", "Felipe Melo", CanalVenda.CORPORATIVO_B2B, new BigDecimal("12000.00"), true)
        );

        // 1. Filtragem de vendas aprovadas e agrupamento por Canal com totalizador
        Map<CanalVenda, BigDecimal> faturamentoPorCanal = historicoVendas.stream()
                .filter(Venda::aprovada) // Predicate
                .collect(Collectors.groupingBy(
                        Venda::canal,
                        Collectors.reducing(BigDecimal.ZERO, Venda::total, BigDecimal::add)
                ));

        System.out.println("📊 FATURAMENTO CONSOLIDADO POR CANAL:");
        faturamentoPorCanal.forEach((canal, total) -> 
            System.out.printf("   Canal: %-18s | Faturamento: R$ %,10.2f%n", canal, total));

        // 2. Ranking de Vendedores (Total Vendido e Quantidade de Vendas)
        System.out.println("\n🏆 RANKING DE PERFORMANCE DOS VENDEDORES:");
        Map<String, List<Venda>> vendasPorVendedor = historicoVendas.stream()
                .filter(Venda::aprovada)
                .collect(Collectors.groupingBy(Venda::vendedor));

        vendasPorVendedor.entrySet().stream()
                .map(e -> {
                    String vendedor = e.getKey();
                    BigDecimal totalVendedor = e.getValue().stream().map(Venda::total).reduce(BigDecimal.ZERO, BigDecimal::add);
                    int qtdVendas = e.getValue().size();
                    return Map.entry(vendedor, Map.entry(totalVendedor, qtdVendas));
                })
                .sorted((e1, e2) -> e2.getValue().getKey().compareTo(e1.getValue().getKey())) // Ordem Decrescente
                .forEach(entry -> {
                    String vendedor = entry.getKey();
                    BigDecimal total = entry.getValue().getKey();
                    int qtd = entry.getValue().getValue();
                    System.out.printf("   Vendedor: %-15s | Volume: R$ %,10.2f | Pedidos: %d%n", vendedor, total, qtd);
                });

        System.out.println("================================================================================");
    }
}