O documento apresenta as principais funcionalidades do Java 8 relacionadas a expressões lambda e Stream API. São descritas interfaces funcionais, expressões lambda, que permitem declarar comportamentos de forma concisa, e a Stream API, que possibilita realizar operações sobre fluxos de objetos de forma encadeada e paralela.
1. Java 8: Expressões Lambda e API de Stream
The Developers Conference 2014 – São Paulo
2. Danival Taffarel Calegari
● Mestre em Ciência da Computação pela Unicamp.
● Mais de 13 anos desenvolvendo aplicações com Java e Java
EE.
● Líder técnico na MATERA Systems
● Instrutor na Globalcode
● Palestras em diversos eventos: JavaOne, TDC, JustJava,
DevCamp, ...
● Certificações: SCJP, SCBCD, SCWCD
3. Agenda
● Por que lambdas e Stream API?
● Interfaces funcionais
● Expressões Lambda
● Stream API
● Referências
4. Por que lambdas e Stream API?
● A língua evolui para tornar a comunicação mais eficiente.
● Altere a posição dos elementos de uma lista de clientes de tal
forma que cada elemento tenha o valor do CPF maior ou igual
ao elemento anterior e que tenha o valor do CPF menor ou
igual ao do elemento posterior.
● Ordene a lista de clientes pelo CPF.
● O verbo “ordenar” nos permite expressar este conceito de
uma forma mais direta e concisa.
5. Por que lambdas e Stream API?
● A linguagem Java tem evoluindo para aumentar seu poder de
expressão:
● Collections API , Generics, Enhanced For Loops (for-each), Typesafe
Enums, Annotations, Autoboxing/Unboxing, Varargs, Fork and Join,
Try-with-resources statement, NIO 2.0, etc.
● Expressões lambda ajudam a remover código repetitivo
(boilerplate).
● Stream API permite o encadeamento de operações sobre
conjuntos de elementos. Também permite o processamento
paralelo ou sequencial em coleções para map-reduce.
6.
7. Interfaces Funcionais
● Interfaces com apenas um método.
● Muito usadas quando é necessário passar um comportamento
(função) como parâmetro.
@FunctionalInterface
public interface Runnable {
void run();
}
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
}
public interface ActionListener extends EventListener {
void actionPerformed(ActionEvent e);
}
8. Expressões Lambda
● Programar bem é encontrar a abstração correta para o
problema a ser resolvido.
List<Cliente> clientes = clienteRepository.getAll();
List<Cliente> clientesFiltrados = new ArrayList<>();
for (Iterator<Cliente> it = clientes.iterator(); it.hasNext();) {
Cliente cliente = it.next();
if (cliente.getIdade() >= 30) {
clientesFiltrados.add(cliente);
}
}
● Código correto, “limpo” e fácil de manter. Mas não é a melhor
abstração.
9. Expressões Lambda
● Criando abstração de filtrar uma lista por um critério.
@FunctionalInterface
interface Criterio<T> {
boolean teste(T objeto);
}
static <T> List<T> filtrar(List<T> lista, Criterio<T> criterio) {
List<T> listaFiltrada = new ArrayList<>();
for (T objeto : lista) {
if (criterio.teste(objeto)) {
listaFiltrada.add(objeto);
}
}
return listaFiltrada;
}
10. Expressões Lambda
● Melhor abstração, mas o código ficou mais “poluído” pela
inclusão das partes “repetitivas” da declaração da classe
anônima.
List<Cliente> clientes = clienteRepository.getAll();
List<Cliente> clientesFiltrados =
Utilitarios.filtrar(clientes, new Criterio<Cliente>() {
@Override
public boolean teste(Cliente cliente) {
return cliente.getIdade() >= 30;
}
});
14. Expressões Lambda
● Apenas para interfaces funcionais.
● Não é apenas “um rostinho bonito” para criar classes
anônimas.
● Utiliza invokedynamic e Nashorn (API de JavaScript) para tornar a
execução mais eficiente.
● Pela primeira vez promoveu mudanças coordenadas no
compilador, na VM e em APIs.
15. Expressões Lambda
Classes que serão utilizadas nos próximos exemplos:
public class Collections {
public static <T> void sort(List<T> list, Comparator<? super T> c) {
// ...
}
// ...
}
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
}
16. Expressões Lambda
● Mais de um parâmetro
Collections.sort(clientes,
(cli1, cli2) -> cli1.getVendas().compareTo(cli2.getVendas()));
● Mais de uma linha
Collections.sort(clientes,
(cli1, cli2) -> {
int comp = cli1.getVendas().compareTo(cli2.getVendas());
if (comp == 0) {
comp = cli1.getNome().compareTo(cli2.getNome());
}
return comp;
});
17. Expressões Lambda
● Sem parâmetros
Executors.callable(
() -> System.out.println("Imprime na thread")).call();
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
19. Stream API
● Operações encadeadas sobre um fluxo de objetos.
● Várias interfaces funcionais representando operações no
pacote java.util.function
● Predicate, Supplier, Consumer, Function, etc.
● Integrado com a API de Collections
● Foi necessário criar implementações default para interfaces para
viabilizar isto!
● Permite realizar operações do tipo map-reduce.
20. Stream API
List<Cliente> clientes = Utilitarios.geraClientes(50);
clientes.stream().forEach(cli -> System.out.println(cli));
● Imprime lista de clientes
List<Cliente> clientesFiltrados =
clientes.stream().filter(cli -> cli.getIdade() > 30)
.sorted(Cliente::comparaVendas).collect(Collectors.toList());
● Filtra clientes com idade menor que 30, ordena por vendas e
gera coleção
List<Cliente> clientesFiltradosParalelo =
clientes.stream().parallel().filter(cli -> cli.getIdade() > 30)
.sorted(Cliente::comparaVendas).collect(Collectors.toList());
● Imprime lista de clientes
21. Stream API
● Divide as operações em intermediárias e finais.
● As operações intermediárias não executam, apenas preparam
as estruturas para execução.
● Nas operações finais as operações intermediárias são
executadas e é produzido um resultado.
● API fortemente inspirada no Guava
(https://code.google.com/p/guava-libraries)
● Isto signifiva que podemos usar mesmo com Java 7, basta importar a
biblioteca para o projeto.
22. Referências
● Página oficial da Oracle com todos os recursos do Java 8
● http://www.oracle.com/technetwork/java/javase/8-whats-new-
2157071.html
● Tutorial da Oracle sobre Expressões Lambda
● http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.
html
● Tutorial da Oracle sobre Stream API
● http://docs.oracle.com/javase/tutorial/collections/streams/index.html