4. “The functional style is not counter to
object-oriented programming (OOP). The real
paradigm shift is from the imperative to
the declarative style of programming. With
Java 8, we can now intermix functional
and OO styles of programming quite
effectively. We can continue to use the OOP
style to model domain entities, their states, and their
relationships. In addition, we can model the behavior
or state transformations, business workflows, and
data processing as a series of functions to form a
function composition.”
5. O que realmente muda no nosso
dia-a-dia usando programação
funcional com Java 8?
6. Ordenando e exibindo uma lista
for (Jogador jogador : listaJogadores) {
if (Posicao.ATACANTE.equals(jogador.getPosicao())) {
listaAtacantes.add(jogador);
}
}
Collections.sort(listaAtacantes, new Comparator<Atletas>() {
@Override
public int compare(Jogador j1, Jogador j2) {
return j1.getNome().compareTo(j2.getNome());
}
});
for (Jogador jogador : listaAtacantes) {
System.out.println(jogador);
} 6
7. Ordenando e exibindo uma lista
listaJogadores.removeIf(jogador -> !Posicao.ATACANTE.equals(jogador.getPosicao()));
listaJogadores.sort((a1, a2) -> a1.getNome().compareTo(a2.getNome()));
listaJogadores.forEach(System.out::println);
7
8. // Java 8
listaJogadores.sort((j1, j2) -> j1.getNome().compareTo(j2.getNome()));
Collections.sort(listaAtacantes, new Comparator<Jogador>() {
@Override
public int compare(Jogador j1, Jogador j2) {
return j1.getNome().compareTo(j2.getNome());
}
});
8
9. // Java 8
listaJogadores.sort((j1, j2) -> j1.getNome().compareTo(j2.getNome()));
Collections.sort(listaAtacantes, new Comparator<Jogador>() {
@Override
public int compare(Jogador j1, Jogador j2) {
return j1.getNome().compareTo(j2.getNome());
}
});
9
10. // Java 8
listaJogadores.sort((j1, j2) -> j1.getNome().compareTo(j2.getNome()));
Collections.sort(listaAtacantes, new Comparator<Jogador>() {
@Override
public int compare(Jogador j1, Jogador j2) {
return j1.getNome().compareTo(j2.getNome());
}
});
10
11. // Java 8
listaJogadores.removeIf(jogador -> !Posicao.ATACANTE.equals(jogador.getPosicao()));
for (Jogador jogador : listaJogadores) {
if (Posicao.ATACANTE.equals(jogador.getPosicao())) {
listaAtacantes.add(jogador);
}
}
11
15. 15
+ legibilidade de código
+ foco no negócio
+ código mais expressivo
+ facilidade de paralelizar o código
- probabilidade de erro
- código imperativo
- mutabilidade
16. O que vamos ver então?
Lambda
Functional interfaces
Method reference
Default methods
Collections API
Streams
16
17. ● Anonima
○ não possui nome
● Função
○ não é vinculada a classe
● Concisa
○ não possui código boilerplate
● Pode ser repassada
○ como argumento ou variável
Lambda Expression
17
18. Anonymous class:
Collections.sort(listaAtacantes, new Comparator<Jogador>() {
@Override
public int compare(Jogador j1, Jogador j2) {
return j1.getNome().compareTo(j2.getNome());
}
});
Lambda:
listaJogadores.sort((j1, j2) -> j1.getNome().compareTo(j2.getNome()));
Lambda Expression
18
24. Comparator<Jogador> c1 = (Jogador j1, Jogador j2) ->
a1.getNome().compareTo(a2.getNome());
Predicate<Jogador> pre = (Jogador j1) -> a1.getNome().startsWith("N");
Object o = (Jogador a1, Jogador a2) ->
a1.getNome().compareTo(a2.getNome());
Atribuindo Lambda para variável
//The target type of this expression must be a functional interface
24
25. ● Interface com 1 único método abstrato
○ Default Methods
● @FunctionalInterface
Functional Interfaces
25
29. // Sem Type Inference
Comparator<Jogador> c1 = (Jogador a1, Jogador a2) ->
a1.getNome().compareTo(a2.getNome());
// Com Type Inference
Comparator<Jogador> c1 = (a1, a2) -> a1.getNome().compareTo(a2.getNome());
Type inference
29
30. Mesma Lambda, diferentes Functional Interfaces
30
● Mesma Lambda, duas Functional Interface diferentes
Comparator<Jogador> c =
(a1, a2) -> a1.getNome().compareTo(a2.getNome());
BiFunction<Jogador, Jogador, Integer> c =
(a1, a2) -> a1.getNome().compareTo(a2.getNome());
31. 31
Dois métodos com mesmo nome, recebendo diferentes Functional Interfaces, porém que
aceitam a mesma Lambda
private void testTypeChecking(BiFunction<Jogador, Jogador, Integer> lambda)
private void testTypeChecking(Comparator<Jogador> lambda)
Ao chamar o método
testTypeChecking((a1, a2) -> a1.getNome().compareTo(a2.getNome()));
o compilador apresenta o erro:
The method testTypeChecking(Comparator<Jogador>) is ambiguous for the type class ...
32. 32
● … porém se passarmos o objeto comp o compilador
sabe qual método chamar
Comparator<Jogador> comp =
(a1, a2) -> a1.getNome().compareTo(a2.getNome());
testTypeChecking(comp);
39. Method References
● Permite referenciar métodos ou construtores usando ::
● Como se fosse uma abreviação de uma lambda, chamando somente um
método
Lambda:
Consumer<String> consumer = (String s) -> System.out.println(s)
Method Reference:
Consumer<String> consumer = System.out::println
39
88. N = tamanho da coleção
Q = custo por elemento no pipeline da stream
N x Q = custo total do pipeline
quanto maior N x Q melhor será a execução em paralelo
88
Simon Ritter
Oracle Java Technology Evangelist
89. Referências
Java 8 in Action
Lambdas, streams, and functional-style
programming
Functional Programming in Java
Introducing Java 8
A Quick-Start Guide to Lambdas and
Streams
Java 8 Prático
Lambdas, Streams e os novos recursos da
linguagem