Java 8: Expressões Lambda e API de Stream
The Developers Conference 2014 – São Paulo
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
Agenda
● Por que lambdas e Stream API?
● Interfaces funcionais
● Expressões Lambda
● Stream API
● Referências
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.
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.
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);
}
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.
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;
}
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;
}
});
Expressões Lambda
● E agora, quem poderá nos ajudar?
Expressões Lambda
List<Cliente> clientes = clienteRepository.getAll();
List<Cliente> clientesFiltrados =
Utilitarios.filtrar(clientes, new Criterio<Cliente>() {
@Override
public boolean teste(Cliente cliente) {
return cliente.getIdade() >= 30;
}
});
Expressões Lambda
List<Cliente> clientes = clienteRepository.getAll();
List<Cliente> clientesFiltrados =
Utilitarios.filtrar(clientes, cli -> cli.getIdade() >= 30);
@FunctionalInterface
interface Criterio<T> {
boolean teste(T objeto);
}
Corpo do Método
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.
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);
}
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;
});
Expressões Lambda
● Sem parâmetros
Executors.callable(
() -> System.out.println("Imprime na thread")).call();
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Expressões Lambda
● Referência de método
String[] stringArray = { "Barbara", "James", "Mary", "John",
"Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, (s1, s2) -> s1.compareToIgnoreCase(s2));
Arrays.sort(stringArray, String::compareToIgnoreCase);
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.
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
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.
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
TDC 2014 - Java 8: Expressões Lambda e API de Stream

TDC 2014 - Java 8: Expressões Lambda e API de Stream

  • 1.
    Java 8: ExpressõesLambda 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 quelambdas e Stream API? ● Interfaces funcionais ● Expressões Lambda ● Stream API ● Referências
  • 4.
    Por que lambdase 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 lambdase 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.
  • 7.
    Interfaces Funcionais ● Interfacescom 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 ● Programarbem é 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 ● Criandoabstraçã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 ● Melhorabstraçã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; } });
  • 11.
    Expressões Lambda ● Eagora, quem poderá nos ajudar?
  • 12.
    Expressões Lambda List<Cliente> clientes= clienteRepository.getAll(); List<Cliente> clientesFiltrados = Utilitarios.filtrar(clientes, new Criterio<Cliente>() { @Override public boolean teste(Cliente cliente) { return cliente.getIdade() >= 30; } });
  • 13.
    Expressões Lambda List<Cliente> clientes= clienteRepository.getAll(); List<Cliente> clientesFiltrados = Utilitarios.filtrar(clientes, cli -> cli.getIdade() >= 30); @FunctionalInterface interface Criterio<T> { boolean teste(T objeto); } Corpo do Método
  • 14.
    Expressões Lambda ● Apenaspara 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 queserã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 ● Maisde 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 ● Semparâmetros Executors.callable( () -> System.out.println("Imprime na thread")).call(); @FunctionalInterface public interface Runnable { public abstract void run(); }
  • 18.
    Expressões Lambda ● Referênciade método String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" }; Arrays.sort(stringArray, (s1, s2) -> s1.compareToIgnoreCase(s2)); Arrays.sort(stringArray, String::compareToIgnoreCase);
  • 19.
    Stream API ● Operaçõesencadeadas 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 ● Divideas 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 oficialda 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