1 O que significa um Stream ser lazy?
Ao manipular um Stream, encadeamos operações formando um pipeline.
O Java otimiza essas operações executando-as somente quando necessário.
A maioria das operações do Stream são lazy, ou seja, não são executadas imediatamente.
2 Exemplo de operações lazy
No código abaixo, filter e sorted não executam nada imediatamente:
usuarios.stream()
.filter(u -> u.getPontos() > 100)
.sorted(Comparator.comparing(Usuario::getNome));
Ambos apenas retornam um novo Stream com essas operações registradas.
Essas operações são chamadas de intermediárias.
3 Quando o Stream realmente é executado?
Somente quando ocorre uma operação terminal, como collect():
List<Usuario> filtradosOrdenados = usuarios.stream()
.filter(u -> u.getPontos() > 100)
.sorted(Comparator.comparing(Usuario::getNome))
.collect(Collectors.toList());
O collect força a execução das operações intermediárias e gera o resultado.
8.3 Qual é a vantagem dos métodos serem lazy?
1 Evita trabalho desnecessário
Exemplo ineficiente: filtra todos os usuários e cria uma lista apenas para pegar um elemento:
Usuario maisDe100 = usuarios.stream()
.filter(u -> u.getPontos() > 100)
.collect(Collectors.toList())
.get(0);
Problemas:
Filtra todos os usuários desnecessariamente.
Cria uma lista temporária.
Pode gerar uma exception se nenhum usuário atender ao critério.
2 Solução otimizada com findAny()
findAny() retorna qualquer usuário que atenda ao critério, sem filtrar toda a lista:
Optional<Usuario> usuarioOptional = usuarios.stream()
.filter(u -> u.getPontos() > 100)
.findAny();
Exemplo: StreamsLazy.java
Vantagens:
Retorna um Optional, permitindo um tratamento seguro.
O Stream para a execução assim que encontra um usuário válido.
3 Diferença entre findAny() e findFirst()
Ambos são operações terminais.
findAny() retorna qualquer elemento rapidamente.
findFirst() respeita a ordem do Stream e retorna o primeiro elemento que satisfaz o critério.
4 Como verificar a otimização?
Pode-se imprimir logs dentro de getPontos() ou usar breakpoints.
Uma abordagem interessante é usar peek(), um método intermediário que permite visualizar a execução:
usuarios.stream()
.peek(u -> System.out.println("Verificando: " + u.getNome()))
.filter(u -> u.getPontos() > 100)
.findAny();
Exemplo: ExemploPeek
Esse código imprime somente até encontrar o primeiro usuário válido, confirmando a otimização.
5 Consideração final
A otimização não é garantida em todos os casos.
Depende das operações no pipeline e do comportamento específico do Stream.
Top comments (0)