I. Operações filter, distinct e skip com Stream
Exemplo de uso básico dessas operações intermediárias.
package exemplos.stream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class DemoStreamBase {
public static void main(String[] args) {
List<Integer> numeros = Arrays.asList(10, 20, 30, 40, 50, 60, 60, 70, 70, 80);
// Filtrar apenas múltiplos de 10
List<Integer> filtrados = numeros.stream()
.filter(n -> n % 10 == 0)
.collect(Collectors.toList());
System.out.println(filtrados); // [10, 20, 30, 40, 50, 60, 60, 70, 70, 80]
// Remover duplicatas
List<Integer> unicos = numeros.stream()
.distinct()
.collect(Collectors.toList());
System.out.println(unicos); // [10, 20, 30, 40, 50, 60, 70, 80]
// Ignorar os primeiros 3 elementos
List<Integer> ignorados = numeros.stream()
.skip(3)
.collect(Collectors.toList());
System.out.println(ignorados); // [40, 50, 60, 60, 70, 70, 80]
// Manter apenas os primeiros 4 elementos
List<Integer> limitados = numeros.stream()
.limit(4)
.collect(Collectors.toList());
System.out.println(limitados); // [10, 20, 30, 40]
}
}
Saída correspondente:
[10, 20, 30, 40, 50, 60, 60, 70, 70, 80]
[10, 20, 30, 40, 50, 60, 70, 80]
[40, 50, 60, 60, 70, 70, 80]
[10, 20, 30, 40]
II. Opperações map e flatMap com Stream
A operação map transforma cada elemento do stream, enquento flatMap é usada para achatar streams aninhados.
package exemplos.stream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class DemoTransformacaoStream {
public static void main(String[] args) {
List<Integer> lista = Arrays.asList(1, 2, 3, 4, 5);
// Dobrar cada valor
List<Integer> dobrados = lista.stream()
.map(valor -> valor * 2)
.collect(Collectors.toList());
System.out.println(dobrados); // [2, 4, 6, 8, 10]
// Extrair nomes de objetos
List<String> nomes = listarProdutos().stream()
.map(Produto::getNome)
.collect(Collectors.toList());
System.out.println(nomes); // [Laptop, Smartphone, Tablet, Monitor]
// Exemplo de flatMap: dividir palavras em caracteres únicos
String[] frases = {"Ola", "Mundo"};
Stream<String[]> streamArrays = Arrays.stream(frases)
.map(f -> f.split(""));
Stream<String> streamCaracteres = streamArrays.flatMap(Arrays::stream);
List<String> caracteresUnicos = streamCaracteres.distinct().collect(Collectors.toList());
System.out.println(caracteresUnicos); // [O, l, a, M, u, n, d]
}
private static List<Produto> listarProdutos() {
return Arrays.asList(
new Produto("Laptop", 1200),
new Produto("Smartphone", 800),
new Produto("Tablet", 400),
new Produto("Monitor", 600)
);
}
// Classe auxiliar para demonstração
static class Produto {
private String nome;
private double preco;
public Produto(String nome, double preco) {
this.nome = nome;
this.preco = preco;
}
public String getNome() {
return nome;
}
}
}
Saída:
[2, 4, 6, 8, 10]
[Laptop, Smartphone, Tablet, Monitor]
[O, l, a, M, u, n, d]
flatMap combina um ou mais streams em um único stream. Pode ser entendido como uma operação de mapeamento seguida de achamento.
III. Operações match, find e reduce com Stream
Operações de correspondência, busca e redução.
package exemplos.stream;
import java.util.Arrays;
import java.util.Optional;
import java.util.stream.Stream;
public class DemoOperacoesTerminais {
public static void main(String[] args) {
Stream<Integer> fluxo = Arrays.asList(5, 10, 15, 20, 25).stream();
// Verificações de correspondência
boolean todosPositivos = fluxo.allMatch(n -> n > 0);
System.out.println(todosPositivos); // true
fluxo = Arrays.asList(5, 10, 15, 20, 25).stream();
boolean algumMaiorQue20 = fluxo.anyMatch(n -> n > 20);
System.out.println(algumMaiorQue20); // true
fluxo = Arrays.asList(5, 10, 15, 20, 25).stream();
boolean nenhumNegativo = fluxo.noneMatch(n -> n < 0);
System.out.println(nenhumNegativo); // true
// Encontrar elementos
fluxo = Arrays.asList(5, 10, 15, 20, 25).stream();
Optional<Integer> primeiroPar = fluxo.filter(n -> n % 2 == 0).findFirst();
primeiroPar.ifPresent(System.out::println); // 10
// Operação de redução: soma
fluxo = Arrays.asList(5, 10, 15, 20, 25).stream();
int soma = fluxo.reduce(0, (acumulador, valor) -> acumulador + valor);
System.out.println(soma); // 75
// Redução: valor máximo
fluxo = Arrays.asList(5, 10, 15, 20, 25).stream();
fluxo.reduce(Integer::max).ifPresent(System.out::println); // 25
}
}
Saída:
true
true
true
10
75
25
IV. Operação peek com Stream
peek é uma operação intermediária para inspeção durante o processamento do stream, útil para depuração.
package exemplos.stream;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class DemoPeek {
public static void main(String[] args) {
// Uso para depuração
List<String> resultado = Stream.of("Java", "Kotlin", "Python", "Go")
.filter(lang -> lang.length() > 3)
.peek(lang -> System.out.println("Filtrado: " + lang))
.map(String::toUpperCase)
.peek(lang -> System.out.println("Mapeado: " + lang))
.collect(Collectors.toList());
System.out.println(resultado);
// Saída: Filtrado: Java, Mapeado: JAVA, Filtrado: Kotlin, Mapeado: KOTLIN, Filtrado: Python, Mapeado: PYTHON
// [JAVA, KOTLIN, PYTHON]
// Observação: peek não é uma operação terminal; ela requer uma operação terminal como collect para executar.
// Diferentemente de forEach, que é terminal e retorna void.
}
}
peek não modifica os elementos, a menos que o objeto seja mutável. Recomenda-se seu uso apenas em ambientes de desenvolvimento e testes para inspecinoar o fluxo de dados.