Desvendando as Operações Terminais em Java Streams: Um Guia Prático
Hoje vamos desvendar juntos as operações terminais em Java Streams, de uma forma mais prática e direta.
O que são essas tais operações finais? Bem, são basicamente aquelas que encerram o processamento de uma stream e produzem um resultado final. Vamos dar uma olhada em algumas delas:
-
forEach: Quer percorrer todos os elementos da sua stream e aplicar uma ação a cada um deles? O forEach é o seu amigo! É ótimo para ações que não retornam valores, como imprimir elementos ou atualizar variáveis.
-
collect: Agora, se você quer transformar os elementos da stream em uma nova coleção ou realizar alguma operação de redução, o collect é o que você precisa. Ele permite que você especifique como deseja agrupar ou reduzir os elementos.
-
reduce: Precisa combinar todos os elementos da stream em um único resultado? O reduce é a escolha certa! Você pode especificar uma função de redução que será aplicada sucessivamente aos elementos, produzindo um resultado final.
-
findFirst e findAny: Ambos são usados para encontrar o primeiro elemento da stream que corresponda a um determinado critério. O findFirst retorna o primeiro elemento encontrado, enquanto o findAny pode retornar qualquer elemento que corresponda ao critério.
-
sum: Calcula a soma dos elementos em uma stream de números.
-
min: Encontra o menor elemento na stream com base em um comparador específico.
-
max: Encontra o maior elemento na stream com base em um comparador específico.
-
count: Retorna o número de elementos na stream.
-
average: Calcula a média dos elementos em uma stream de números.
Então, quando usar cada uma dessas operações? Bem, isso depende do que você precisa fazer! Abaixo trago uma lista de exemplos para tentar ajudar na escolha:
Exemplos
forEach
Imagine que você tem uma lista de festas e quer imprimir o nome de cada uma delas. Para isso, você pode usar o forEach
assim:
listaDeFestas.stream().forEach(festa -> System.out.println("Nome da festa: " + festa.getNome()));
Essa operação percorre todos os elementos da stream e executa a ação definida dentro do forEach
para cada um deles.
collect
Agora, suponha que você quer criar uma lista com os nomes das festas. Você pode fazer isso usando o collect da seguinte forma:
var nomesDasFestas = listaDeFestas.stream()
.map(Festa::getNome)
.collect(Collectors.toList());
Aqui, a operação map
é usada para extrair o nome de cada festa e, em seguida, o collect é utilizado para agrupar esses nomes em uma lista.
reduce
Vamos imaginar que você queira calcular o valor total de todas as festas. Nesse caso, você pode usar o reduce assim:
double valorTotalDasFestas = listaDeFestas.stream()
.mapToDouble(Festa::getValor)
.reduce(0, (subtotal, elemento) -> subtotal + elemento);
Aqui, primeiro transformamos o valor de cada festa em um Double
usando o mapToDouble
e, em seguida, utilizamos o reduce
para somar esses valores, começando com um valor inicial de 0.
findFirst e findAny
Se você precisa encontrar o primeiro elemento que corresponde a um determinado critério, pode usar o findFirst. Já o findAny pode ser usado para encontrar qualquer elemento que corresponda ao critério.
Imagine que você quer encontrar a primeira festa que ocorreu em uma determinada localização. Você pode fazer isso usando o findFirst da seguinte forma:
Optional<Festa> primeiraFesta = listaDeFestas.stream()
.filter(festa -> festa.getLocal().equals("Pato Branco"))
.findFirst();
Neste exemplo, usamos o filter
para restringir a stream
apenas às festas que ocorreram em "Pato Branco" e, em seguida, utilizamos o findFirst
para encontrar a primeira festa que corresponde a esse critério.
sum
Se você quer calcular a soma de dos custos de todas as festsa, pode usar o sum. Por exemplo:
double somaDosCustosDeTodasAsFetas = listaDeFestas.stream()
.mapToDouble(Festa::getCusto)
.sum();
max e min
Se você precisa encontrar o custo máximo ou mínimo dentre todas as festas, pode usar o max e o min. Por exemplo:
OptionalDouble custoMaximo = listaDeFestas.stream()
.mapToDouble(Festa::getCusto)
.max();
OptionalDouble custoMinimo = listaDeFestas.stream()
.mapToDouble(Festa::getCusto)
.min();
count
Se você quer contar a quantidade de festas que realizou em uma determinada cidade, pode usar o count. Por exemplo:
long quantidadeDeFestasEmPatoBranco = listaDeFestas.stream()
.filter(festa -> festa.getLocal().equals("Pato Branco"))
.count();
average
Se você quer calcular o custo médio das festas, pode usar o average. Por exemplo:
OptionalDouble mediaDosValoresDasFestas = listaDeFestas.stream()
.mapToDouble(Festa::getCusto)
.average();
Conclusão
As operações terminais em Java Streams são servem para manipular e analisar coleções de dados de forma eficiente. Cada uma dessas operações tem seu próprio propósito e pode ser aplicada em diferentes cenários, dependendo das necessidades do seu programa.
O forEach é ideal quando você precisa executar uma ação para cada elemento da stream, como imprimir ou processar os elementos. O collect é útil para agrupar elementos em uma nova coleção ou realizar operações de redução. O reduce é adequado para combinar todos os elementos da stream em um único resultado. E o findFirst e findAny são úteis para encontrar elementos específicos dentro da stream.
Além disso, as operações adicionais como sum, min, max, count e average oferecem funcionalidades específicas para calcular estatísticas sobre os dados na stream.
Ao escolher a operação terminal correta, você pode simplificar o seu código e torná-lo mais eficiente, facilitando o processamento e análise de grandes conjuntos de dados em Java. Espero que este guia prático ajude você a entender melhor como utilizar essas operações terminais em suas aplicações Java. Experimente aplicá-las em seus projetos e explore todo o potencial das Java Streams!