1 Melhoria na Ordenação de Coleções
A ordenação de coleções foi aprimorada com novos recursos da linguagem a partir do Java 8.
O objetivo é tornar o código mais conciso e legível.
Exemplo: Ordenação e Modificação de Usuários
Código Moderno:
Ordena os usuários pelo número de pontos (ordem decrescente).
Seleciona os 10 primeiros e os torna moderadores.
Mais compacto e direto.
usuarios.sort(Comparator.comparing(Usuario::getPontos).reversed());
usuarios
.subList(0,10)
.forEach(Usuario::tornaModerador);
Arquivo: Seleciona10.java
Código Antigo (Pré-Java 8)
Uso explícito da interface Comparator para ordenar.
Inversão da lista após a ordenação.
Iteração manual para modificar os 10 primeiros usuários.
Collections.sort(usuarios, new Comparator<Usuario>() {
@Override
public int compare(Usuario u1, Usuario u2) {
return u1.getPontos() - u2.getPontos();
}
});
Collections.reverse(usuarios);
List<Usuario> top10 = usuarios.subList(0, 10);
for (Usuario usuario : top10) {
usuario.tornaModerador();
}
Arquivo: Seleciona10Antigo.java
2 Streams: tornando moderadores os usuários com mais de 100 pontos
Filtragem Tradicional em Java (Pré-Java 8):
Uso de um laço for para percorrer a coleção.
Aplicação de uma condição if para filtrar os elementos desejados.
Código imperativo e verboso, exigindo mais blocos de código para cada nova condição.
Exemplo para tornar moderadores os usuários com mais de 100 pontos:
for (Usuario usuario : usuarios) {
if (usuario.getPontos() > 100) {
usuario.tornaModerador();
}
}
Arquivo: Moderador100Ponto.java
A Falta do Método filter na API de Collections
Diferente de sort (presente em List) e forEach (presente em Iterable), filter não foi adicionado diretamente a Collection ou List.
Razões para essa decisão:
API de Collection já era grande e difícil de evoluir sem quebrar compatibilidade.
Padrão comum de uso identificava a necessidade de operações encadeadas.
Evitar a criação de variáveis intermediárias para armazenar resultados parciais.
Introdução ao Stream no Java 8
O Stream foi criado para trabalhar com coleções de forma funcional e fluente.
Não altera a coleção original e evita efeitos colaterais.
Criando um Stream a partir de uma Lista
- Novo método stream() adicionado na interface Collection:
Stream<Usuario> stream = usuarios.stream();
- O método filter() recebe um Predicate e permite filtrar elementos:
Stream<Usuario> stream = usuarios.stream()
.filter(u -> u.getPontos() > 100);
- Pode ser simplificado removendo a variável intermediária:
usuarios.stream()
.filter(u -> u.getPontos() > 100);
Arquivo: Moderador100PontoStreams.java
Streams Não Modificam a Coleção Original
filter() e outros métodos de Stream não alteram a lista original.
Exemplo mostrando que a filtragem não afeta a lista original:
usuarios.stream()
.filter(u -> u.getPontos() > 100);
usuarios.forEach(System.out::println); // Exibe todos os usuários
- Para aplicar a transformação corretamente, é necessário armazenar o novo Stream e processá-lo:
usuarios.stream()
.filter(u -> u.getPontos() > 100)
.forEach(System.out::println);
Arquivo: MantemOriginal.java
Stream Não é uma Coleção
Diferente de uma List, Stream não armazena dados.
Ele é mais parecido com um Iterator, processando elementos sob demanda.
Opera como um pipeline, permitindo encadeamento fluente de métodos.
Uso Fluente do Stream
- Melhor prática: encadear diretamente as operações sem criar variáveis intermediárias:
usuarios.stream()
.filter(u -> u.getPontos() > 100)
.forEach(System.out::println);
O método forEach() retorna void, finalizando o fluxo do Stream.
Para novas operações, deve-se chamar stream() novamente.
Exemplo Completo: Filtrar e Tornar Usuários Moderadores
- Código otimizado com Stream:
usuarios.stream()
.filter(u -> u.getPontos() > 100)
.forEach(Usuario::tornaModerador);
Arquivo: FiltraModerador.java
Uso de Method Reference no filter
- Quando o filter chama um único método de uma classe, pode-se usar Method Reference:
usuarios.stream()
.filter(Usuario::isModerador);
Arquivo: FiltraModerador.java
Top comments (0)