O documento descreve as principais novidades da Java 8, incluindo lambdas, métodos de referência, interfaces funcionais, melhorias na API Stream e na API de datas com o pacote java.time. O foco é explicar 5 dessas features chave: lambdas, métodos de referência, métodos default, API Stream e a nova API de datas no pacote java.time.
2. 55 novas features
Documentação Oracle
Mas falaremos somente sobre 5 delas…
Linguagem
Lambda Expressions
Method Reference
Default Method
API
Stream
Date-Time
7. Por que Lambda no Java?
● 1 linha de código ao invés de 5;
● programação funcional;
● referência de métodos;
● Streams -> Filter/Map/Reduce;
● execução mais rápida que Classe Anônima;
8. Quase função de 1º ordem…
● pode ser passada como parâmetro;
● pode ser retornada em um método;
● pode ser armazenada em uma variável;
Por que quase?
Não existe um tipo função de verdade na JVM;
O java converte lambda em interfaces funcionais;
14. Inferências
@FunctionalInterface
public interface Testable {
public boolean test(int a, int b);
}
"hum, deve retornar um
boolean".
"hum, recebe 2
parâmetros do tipo
int"
new Test().execute(2, 4, (a, b) -> a > b))
class Test {
public boolean execute(int a, int b,
Testable testable) {
return testable.test(a, b);
}
}
16. Novo Pacote: java.util.function
Predicate<T> - método com um parâmetro do tipo T e retorno do tipo boolean.
T -> boolean
Consumer<T> - método com um parâmetro do tipo T e sem retorno.
T -> {}
Function<T, R> - método com um parâmetro do tipo T e retorno do tipo R.
T -> R
Supplier<T> - método sem parâmetros e retorno do tipo T.
() -> T
BiFunction<T, R, U> - método com dois parâmetros. um do tipo T outro do tipo R e retorno do tipo U.
(T, R) -> U
17. Referência de Métodos
Lambda Método
x -> String.valueOf(x) String::valueOf
x -> x.toString() Object::toString
() -> new ArrayList<>() ArrayList::new
19. 4 Tipos de Method Reference
Tipo Sintaxe Exemplo
Referência a um método estático Class:staticMethodName String::valueOf
Referência a um método de uma
instância
object:instanceMethodName x::toString
Referência a um método de uma
instância arbritária qualquer, desde
que seja do tipo Class
Class::instanceMethodName String::toString
Referencia a um construtor ClassName::new String::new
24. Anatomia da API Stream
filter(x -> x > 3)
sorted((a, b) -> a.compareTo(b))
map(x -> x * 2)
forEach(x -> System.out.println(x))
PIPELINE
Fonte ->
{Collections,
Iterator,
Resources,
Generators}
Operação de
Finalização ->
produzem resultados
finais
Operações
Intermediárias
25. Criando Stream
Versão varargs
Stream.of(varargs...)
Versão Infinita
Stream.generate(Supplier<T>) -> tem o método T get()
Versão Infinita
Stream.iterate(seed, UnaryOperator<T> f) -> tem o método <T> UnaryOperator<T>identity()
Versão Strem a partir de um List
Stream<Integer> number = Arrays.asList(1, 2, 3).stream()
Versão paralela
Stream<Integer> number = Arrays.asList(1, 2, 3).parallelStream()
26. Tipos de Operações
Intermediárias
● Sempre retornam um novo Stream;
● Executam quantas operações encadeadas forem necessárias;
● Não inicia o pipeline de execução;
...métodos
● distinct()
● sorted()
● sorted(Comparator)
● limit(long)
● map(Function)
● filter(Predicate)
27. Tipos de Operações
Finalização
● Pode retornar um objeto, uma collection, ou void;
● Inicia o pipeline de execução;
● Depois de executar esta fase, o Stream, não pode ser reutilizado;
...métodos
● reduce(BinaryOperator)
● forEach(Consume)
● findFirst()
● noneMatch(Predicate)
● collect()
28. Collection vs Stream
Sequência de elementos Sequência de elementos
Estrutura de dados em memória Elementos percorridos uma única vez
Iteração externa Iteração interna
Tamanho finito Tamanho também pode ser infinito
Pode alterar a própria Coleção Retorna sempre um novo Stream
29. Iterando sobre uma Collection
● Verboso;
● Paralelismo manual;
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
List<Integer> evenNumbers = new ArrayList<>();
for (Integer number : numbers) {
if (number % 2 == 0) {
evenNumbers.add(i);
}
}
30. Iterando sobre um Stream
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
//versão normal
List<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0).collect(toList());
//versão paralela
List<Integer> evenNumbers = numbers.parallelStream().filter(n -> n % 2 == 0).collect(toList());
● API Fluente: processo de execução encadeado;
● Execução Lazy: elementos computados somente quando necessários;
● Paralelismo Nativo com a utilização do método .parallelStream();
31. Guava
private void removeDuplicate(Iterable<Sale> sales) {
final Iterable<Long> inscriptionIds = transform(sales, new Function<Sale, Long>() {
@Override
public Long apply(Sale input) {
return input.getInscriptionId();
}
});
final List<Sale> existentSales = new ArrayList<Sale>();
existentSales.addAll(saleRepository.findByInscriptionIdInAndType(inscriptionIds, ORIGINAL));
removeIf(sales, new Predicate<Sale>() {
@Override
public boolean apply(final Sale sale) {
return any(existentSales, new Predicate<Sale>() {
@Override
public boolean apply(final Sale input) {
return sale.getInscriptionId().equals(input.getInscriptionId());
}
});
}
});
}
}
33. Nova API de Datas
● Package java.time
● Baseada na biblioteca Joda-Time
● Substitui as problemáticas java.util.Date e java.util.
Calendar
● Divisão de conceitos:
○ Datas para humanos (dia, hora, mês, dia da semana…)
○ Datas para computadores (milisegundos, nanosegundos, instantes…)
34. Nova API de Datas
● Date
LocalDate hoje = LocalDate.now();
System.out.println(hoje); // 2014-11-07 (formato ISO-8601 yyyy-MM-dd)
LocalDate natal = LocalDate.of(2014, Month.DECEMBER, 25);
System.out.println(natal); // 2014-12-25
System.out.println(natal.getDayOfWeek().toString()); // THURSDAY (imprime por extenso)
System.out.println(natal.plusDays(7)); // 2015-01-01
● Time
LocalTime time = LocalTime.now();
System.out.println(time); // 12:01:45.382
System.out.println(time.getHour()); // 12
System.out.println(time.getSecond()); // 45
System.out.println(time.plusHours(1)); // 13:01:45.382
35. Nova API de Datas
● DateTime
LocalDateTime dateTime = LocalDateTime.now();
System.out.println(dateTime); // 2014-11-07T12:01:45.382
● Timezone
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("Europe/Paris"));
System.out.println(zonedDateTime); // 2014-11-06T21:28:02.102+01:00[Europe/Paris]
OffsetDateTime offsetDateTime = OffsetDateTime.now(ZoneId.of("+07:00"));
System.out.println(offsetDateTime); // 2014-11-07T03:28:02.102+07:00]