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

\n\n

A programação funcional (PF) em Java deixou de ser apenas uma tendência da moda — é uma parte essencial da linguagem moderna desde a versão 8. Para desenvolvedores que dominam lambdas básicas e Stream API, chega a fase em que é necessário compreender conceitos mais profundos: mônadas, composição de funções, avaliação preguiçosa e estruturas de dados imutáveis. Este artigo é dedicado a técnicas avançadas de programação funcional em Java que ajudam a escrever código mais limpo, previsível e seguro para paralelismo.

\n\n

1. Composição de Funções e Currying

\n\n

Em Java, as interfaces funcionais Function, Predicate e Consumer fornecem métodos padrão para composição: andThen() e compose(). Isso permite construir cadeias de transformações sem criar variáveis intermediárias.

\n\n

Exemplo de composição:

\n
import java.util.function.Function;\n\npublic class FunctionComposition {\n    public static void main(String[] args) {\n        Function<String, String> trim = String::trim;\n        Function<String, String> toUpper = String::toUpperCase;\n        Function<String, String> addExclamation = s -> s + "!";\n\n        // Composição: trim -> toUpper -> addExclamation\n        Function<String, String> process = trim.andThen(toUpper).andThen(addExclamation);\n\n        String result = process.apply("  hello world  ");\n        System.out.println(result); // HELLO WORLD!\n    }\n}
\n\n

Currying é a transformação de uma função de vários argumentos em uma sequência de funções de um único argumento. Em Java, isso pode ser simulado com lambdas aninhadas:

\n\n
import java.util.function.Function;\n\npublic class CurryingExample {\n    // Função normal\n    static int add(int a, int b) { return a + b; }\n\n    // Versão curried\n    static Function<Integer, Function<Integer, Integer>> curriedAdd = a -> b -> a + b;\n\n    public static void main(String[] args) {\n        // Aplicação parcial\n        Function<Integer, Integer> add5 = curriedAdd.apply(5);\n        System.out.println(add5.apply(3)); // 8\n        System.out.println(add5.apply(10)); // 15\n    }\n}
\n\n

Currying é útil para criar funções especializadas baseadas em padrões gerais, especialmente ao trabalhar com configurações.

\n\n

2. Trabalho Avançado com Stream API

\n\n

O Stream API em Java não é apenas uma substituição para loops. Compreender seus recursos avançados permite aumentar significativamente o desempenho e a legibilidade do código.

\n\n

2.1. Streams paralelos e Spliterators

\n

Streams paralelos usam ForkJoinPool. No entanto, sua eficiência depende do tamanho dos dados e da natureza das operações. Para controle personalizado do paralelismo, pode-se usar Spliterator.

\n\n
import java.util.Spliterator;\nimport java.util.stream.Stream;\nimport java.util.stream.StreamSupport;\n\npublic class CustomSpliterator {\n    public static void main(String[] args) {\n        // Criando um stream a partir de um iterador com spliterator personalizado\n        Spliterator<Integer> spliterator = new Spliterator<>() {\n            int current = 0;\n            @Override\n            public boolean tryAdvance(java.util.function.Consumer<? super Integer> action) {\n                if (current < 100) {\n                    action.accept(current++);\n                    return true;\n                }\n                return false;\n            }\n            @Override\n            public Spliterator<Integer> trySplit() {\n                // Divisão mais simples\n                int mid = current + 50;\n                if (mid >= 100) return null;\n                Spliterator<Integer> prefix = new RangeSpliterator(curre                

Blogs

Book Recommendations