API Stream do Java e Classes Funcionais
A API Stream do Java foi introduzida no Java 8 como uma forma de
processar coleções de maneira declarativa e funcional. Streams
permitem a manipulação de grandes volumes de dados de forma
eficiente, facilitando operações como filtragem, transformação e
agregação.
Além da API Stream, o Java 8 trouxe várias interfaces funcionais na
biblioteca [Link] que podem ser usadas para processar
dados em Streams. Algumas dessas interfaces incluem
BinaryOperator, Consumer, Function, Predicate, Supplier e Optional.
Vamos explorar cada um desses conceitos detalhadamente.
1. API Stream do Java
O que é um Stream?
Um Stream no Java representa uma sequência de elementos que
podem ser processados em pipeline (sequência de operações).
Streams podem ser sequenciais ou paralelos, tornando o
processamento mais eficiente.
Operações com Streams
As operações em Streams podem ser classificadas em dois tipos:
Intermediárias: Produzem um novo Stream e permitem
encadeamento.
Finais: Produzem um resultado e encerram o Stream.
Criando Streams
Podemos criar Streams a partir de diferentes fontes, como listas,
arrays e arquivos:
import [Link];
import [Link];
public class StreamExample {
public static void main(String[] args) {
List<String> nomes = [Link]("Ana", "Bruno", "Carlos",
"Daniela");
Stream<String> stream = [Link]();
[Link]([Link]::println);
Operações Intermediárias
1. filter(Predicate<T>) → Filtra elementos com base em uma
condição:
[Link]()
.filter(nome -> [Link]("A"))
.forEach([Link]::println); // Ana
2. map(Function<T, R>) → Transforma cada elemento:
[Link]()
.map(String::toUpperCase)
.forEach([Link]::println); // ANA, BRUNO, CARLOS, DANIELA
3. sorted() → Ordena os elementos:
[Link]()
.sorted()
.forEach([Link]::println); // Ana, Bruno, Carlos, Daniela
Operações Finais
1. collect([Link]()) → Converte o Stream de volta
para uma lista:
import [Link];
import [Link];
List<String> listaOrdenada = [Link]()
.sorted()
.collect([Link]());
2. count() → Retorna o número de elementos:
long count = [Link]().count();
[Link](count); // 4
2. Interfaces Funcionais do Java
2.1 BinaryOperator
Usada para operações binárias que retornam um resultado do mesmo
tipo dos argumentos.
import [Link];
BinaryOperator<Integer> soma = (a, b) -> a + b;
[Link]([Link](5, 10)); // 15
2.2 Consumer
Representa uma operação que aceita um argumento e não retorna
resultado.
import [Link];
Consumer<String> imprimir = [Link]::println;
[Link]("Olá, Mundo!");
2.3 Function<T, R>
Representa uma função que recebe um argumento e retorna um
resultado.
import [Link];
Function<String, Integer> tamanho = String::length;
[Link]([Link]("Java")); // 4
2.4 Predicate
Representa uma condição booleana sobre um argumento.
import [Link];
Predicate<Integer> isPar = num -> num % 2 == 0;
[Link]([Link](10)); // true
2.5 Supplier
Fornece um valor sem receber argumentos.
import [Link];
Supplier<Double> aleatorio = Math::random;
[Link]([Link]());
2.6 Optional
Evita NullPointerException ao lidar com valores que podem ser
ausentes.
import [Link];
Optional<String> nome = [Link](null);
[Link]([Link]("Nome padrão")); // Nome padrão
3. Integração entre API Stream e Interfaces Funcionais
Podemos usar essas interfaces junto com Streams para tornar o
código mais conciso e legível.
Exemplo: Usando Predicate com filter()
Predicate<String> startsWithA = nome -> [Link]("A");
[Link]()
.filter(startsWithA)
.forEach([Link]::println);
Exemplo: Usando Function com map()
Function<String, String> toUpperCase = String::toUpperCase;
[Link]()
.map(toUpperCase)
.forEach([Link]::println);
Exemplo: Usando Consumer com forEach()
Consumer<String> print = [Link]::println;
[Link]().forEach(print);
Conclusão
A API Stream do Java, junto com as interfaces funcionais, fornece uma
maneira poderosa e expressiva de manipular coleções de dados de
maneira eficiente e concisa. Usando essas ferramentas corretamente,
podemos escrever código mais legível, modular e funcional.
Benefícios:
Imutabilidade: Evita modificações indesejadas.
Paralelismo: Suporte a processamento paralelo
com .parallelStream().
Legibilidade: Código mais expressivo e fácil de entender.
Com esse conhecimento, você pode melhorar sua programação em
Java e tornar seu código mais eficiente!