Voltar para o Blog

Programação Funcional em Java: Lambdas, Streams e Código Declarativo

12 min de leitura
JavaFunctional ProgrammingStreamsLambdas

A programação funcional no Java não é mais uma novidade, mas muitos desenvolvedores ainda não exploram todo o potencial das ferramentas introduzidas desde o Java 8. Vamos explorar como escrever código mais limpo, seguro e performático.

O Paradigma Funcional no Mundo Java

Tradicionalmente imperativo e orientado a objetos, o Java evoluiu para um ecossistema multi-paradigma. A programação funcional foca em o que deve ser feito, em vez de como fazer, priorizando imutabilidade e funções puras.

Lambda Expressions: O Início de Tudo

Lambdas permitem tratar funções como cidadãos de primeira classe, possibilitando passar blocos de código como argumentos para métodos.

// Antes (Classe Anônima)
Collections.sort(nomes, new Comparator<String>() {
    public int compare(String a, String b) {
        return a.compareTo(b);
    }
});

// Depois (Lambda)
nomes.sort((a, b) -> a.compareTo(b));

// Melhor ainda (Method Reference)
nomes.sort(String::compareTo);

Stream API: Processamento de Dados Elegante

Streams permitem processar coleções de dados de forma declarativa e paralela. Elas não alteram a fonte original, promovendo a imutabilidade.

Operações Comuns em Streams

List<String> resultado = pessoas.stream()
    .filter(p -> p.getIdade() > 18)          // Filtro
    .map(Pessoa::getNome)                   // Transformação
    .sorted()                                // Ordenação
    .limit(10)                               // Curto-circuito
    .collect(Collectors.toList());           // Coleta

Trabalhando com Optional

O Optional foi introduzido para mitigar o famoso NullPointerException. Ele força o desenvolvedor a lidar explicitamente com a ausência de valor.

// Abordagem funcional com Optional
public String findUserEmail(Long id) {
    return userRepository.findById(id)
        .map(User::getEmail)
        .orElse("email@naofornecido.com");
}

Imutabilidade com Java Records

A imutabilidade é um pilar da programação funcional. Com os Records (introduzidos no Java 14/16), ficou muito mais fácil criar Data Transfer Objects (DTOs) imutáveis.

public record Product(String name, BigDecimal price) {
    // Todos os campos são finais (final)
    // Getter, equals, hashCode e toString gerados automaticamente
}

Funções de Alta Ordem

Em Java, qualquer interface com apenas um método abstrato (Functional Interface) pode ser representada por um Lambda. As principais são:

  • Predicate: Recebe um valor e retorna um booleano.
  • Function: Recebe um valor e retorna outro.
  • Consumer: Recebe um valor e não retorna nada.
  • Supplier: Não recebe nada e retorna um valor.

Conclusão

Adotar práticas funcionais no Java resulta em código mais conciso, menos propenso a bugs de estado e mais fácil de testar. No entanto, o equilíbrio é chave: não force o uso de Streams em cenários onde um loop for simples seria mais legível.