Programação Funcional em Java: Técnicas Avançadas e Stream API

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Programação Funcional em Java: nível avançado



Programação Funcional (PF) é um paradigma onde os cálculos são tratados como avaliação de funções matemáticas, evitando mudanças de estado e dados mutáveis. Java, sendo uma linguagem orientada a objetos, a partir do Java 8 recebeu ferramentas poderosas para PF: expressões lambda, Stream API e interfaces funcionais. Em nível avançado, essas capacidades permitem escrever código mais conciso, seguro e expressivo, especialmente ao trabalhar com coleções, operações assíncronas e tratamento de erros.



Neste artigo, exploraremos técnicas avançadas de programação funcional em Java: composição de funções, mônadas (Optional e CompletableFuture), Stream API com processamento paralelo e currying.



1. Composição de funções e interfaces funcionais



Em Java, interfaces funcionais são interfaces com um único método abstrato (SAM). As mais usadas são: Function<T, R>, Predicate<T>, Consumer<T> e Supplier<T>. O uso avançado inclui composição de funções com os métodos andThen() e compose().



Exemplo: cadeia de transformações



import java.util.function.Function;

public class FunctionComposition { public static void main(String[] args) { // Função: string -> seu comprimento Function<String, Integer> lengthFunction = String::length; // Função: número -> seu quadrado Function<Integer, Integer> squareFunction = x -> x * x;

// Composição: string -> comprimento -> quadrado do comprimento Function<String, Integer> composedFunction = lengthFunction.andThen(squareFunction);

String text = "Hello, Java!"; int result = composedFunction.apply(text); // 12 * 12 = 144 System.out.println("Resultado: " + result); // 144 }}


O método andThen() aplica a primeira função, depois a segunda. compose() faz o inverso: primeiro aplica a função passada, depois a primeira. Isso permite construir cadeias de transformação flexíveis e reutilizáveis.



Exemplo prático: filtragem e transformação de lista



import java.util.List;import java.util.function.Function;import java.util.function.Predicate;import java.util.stream.Collectors;

public class PredicateAndFunction { public static void main(String[] args) { List<String> names = List.of("Alice", "Bob", "Charlie", "David", "Eve");

Predicate<String> startsWithA = s -> s.startsWith("A"); Function<String, String> toUpperCase = String::toUpperCase;

List<String> result = names.stream() .filter(startsWithA) .map(toUpperCase) .collect(Collectors.toList());

System.out.println(result); // [ALICE] }}


2. Mônadas em Java: Optional e CompletableFuture



Mônada é um padrão que encapsula um valor e fornece operações para transformá-lo sem desempacotamento explícito. Em Java, as mônadas são implementadas através de Optional (para tratamento de null) e CompletableFuture (para operações assíncronas).



Optional como mônada

Os métodos map(), flatMap() e filter() permitem trabalhar encadeadamente com a possível ausência de valor.



import java.util.Optional;

public class OptionalMonad { public static void main(String[] args) { // Criando um Optional com valor não vazio Optional<String> optional = Optional.of("Hello");

// Cadeia de transformações String result = optional .filter(s -> s.length() > 3) // filtro .m

Blogs

Book Recommendations