Estudos do livro Java 8 Prático - Casa do Código
Evolução do Java
Java 5 (2004)
- Introdução de generics, enums e anotações
Java 8 (2014)
Introdução de lambda e method references
Atualizações na API de Collections
Streams
Métodos default
Lambda
Exemplo:
Classe Usuario com os atributos:
pontos (pontuação do usuário)
nome (nome do usuário)
moderador (booleano indicando se é moderador)
class Usuario {
private String nome;
private int pontos;
private boolean moderador;
public Usuario(String nome, int pontos) {
this.pontos = pontos;
this.nome = nome;
this.moderador = false;
}
public String getNome() {
return nome;
}
public int getPontos() {
return pontos;
}
public void tornaModerador() {
this.moderador = true;
}
public boolean isModerador() {
return moderador;
}
}
O primeiro exemplo usará a abordagem clássica, sem recursos novos do Java 8.
public class Capitulo2 {
public static void main(String ... args) {
Usuario user1 = new Usuario("Paulo Silveira", 150);
Usuario user2 = new Usuario("Rodrigo Turini", 120);
Usuario user3 = new Usuario("Guilherme Silveira", 190);
List<Usuario> usuarios = Arrays.asList(user1, user2, user3);
for(Usuario u : usuarios) {
System.out.println(u.getNome());
}
}
}
Arrays.asList cria uma lista imutável rapidamente.
Alternativamente, poderia ser usada uma ArrayList e adicionar elementos manualmente.
Desde o Java 5, é possível usar o for-each para percorrer: Arrays, coleções e objetos que implementam Iterable.
Novo Método forEach em Coleções
Introduzido no Java 8 para facilitar iteração sobre coleções.
Recebe um argumento do tipo Consumer, uma interface funcional do java.util.function.
usuarios.forEach(...);
Arquivo: Capitulo2Exemplo2.java
Implementação do Consumer
class Mostrador implements Consumer<Usuario> {
public void accept(Usuario u) {
System.out.println(u.getNome());
}
}
Arquivo: Mostrador.java
- O método accept executa uma ação sobre cada elemento (imprimir nome do usuário).
Passando a classe para o forEach:
Mostrador mostrador = new Mostrador();
usuarios.forEach(mostrador);
Arquivo: Capitulo2Exemplo3.java
Uso de Classe Anônima
usuarios.forEach(new Consumer<Usuario>() {
public void accept(Usuario u) {
System.out.println(u.getNome());
}
});
Arquivo: Capitulo2Exemplo4.java
- Gera um arquivo .class com nome interno estranho (ex.: Capitulo2$1.class).
Que entre o Lambda!
Em vez de escrever:
Consumer<Usuario> mostrador = new Consumer<Usuario>() {
public void accept(Usuario u) {
System.out.println(u.getNome());
}
};
Podemos escrever:
Consumer<Usuario> mostrador =
(Usuario u) -> {System.out.println(u.getNome());};
Arquivo: Capitulo2Exemplo5.java
Uso de Lambda no forEach
(Usuario u) -> { System.out.println(u.getNome()); }
- O compilador infere que se trata de um Consumer e o mapeia para o método accept automaticamente.
Simplificação do Lambda
1 O compilador pode inferir o tipo, removendo Usuario e os parênteses:
Consumer<Usuario> mostrador = u -> { System.out.println(u.getNome()); };
2 Se houver apenas uma instrução, {} e ; podem ser omitidos:
Consumer<Usuario> mostrador = u -> System.out.println(u.getNome());
3 Pode ser passado diretamente para forEach, sem variável temporária:
usuarios.forEach(u -> System.out.println(u.getNome()));
Arquivo: Capitulo2Exemplo6.java
Lambda vs. Classe Anônima
- Diferente das classes anônimas (Capitulo2$N.class), lambdas são tratados de forma mais otimizada pelo compilador.
Alterando Objetos
usuarios.forEach(u -> u.tornaModerador());
- A variável u não pode ter sido declarada no mesmo escopo, pois lambdas podem capturar variáveis externas (será explorado depois).
Top comments (0)