Novidades da versão 8 do Java: métodos de extensão para interfaces; expressões lambda; referências para métodos; streams e operações em massa para coleções; e nova API DateTime.
2. 14/10/2015
2
Uma plataforma de
desenvolvimento de
software,
Que contém uma
linguagem de mesmo
nome e
Uma extensa e flexível
API.
14/10/2015 (C) 2015, Jandl. 3
20 anos de existência.
8 versões.
Linguagem de
programação mais usada
da atualidade.
Milhões de downloads do
JDK.
14/10/2015 (C) 2015, Jandl. 4
Linguagem OO,
Sintaxe simples (C/C++),
Fortemente tipada,
Independente de
plataforma,
Dotada de coleta de lixo,
Dinâmica, extensível,
segura, multithreaded e
Alto desempenho.
Suporta herança simples,
definição de interfaces,
reflexão, genéricos e
lambdas.
3. 14/10/2015
3
14/10/2015 (C) 2015, Jandl. 5
Versão com o maior número de adições
substanciais desde a versão 5:
Métodos de extensão para interfaces
Expressões Lambda
Referências para métodos
Streams e operações em massa para coleções
NovaAPI DateTime
Paralelização de operações
Anotações melhoradas
14/10/2015 (C) 2015, Jandl. 6
Conteúdo deste
minicurso!
4. 14/10/2015
4
14/10/2015 (C) 2015, Jandl. 7
Templo Borobudur, Java, Indonésia.
As interfaces são essenciais dentro do projeto orientado a objetos e o
Java 8 traz novas possibilidades para sua evolução.
14/10/2015 8(C) 2015, Jandl.
5. 14/10/2015
5
Conjunto dos elementos visíveis nos objetos
de uma classe:
Denomina os atributos e operações expostos para
outras classes e objetos.
Métodos e campos públicos de um objeto
constituem sua interface.
14/10/2015 (C) 2015, Jandl. 9
14/10/2015 (C) 2015, Jandl. 10
6. 14/10/2015
6
Java (e outras linguagens de programação)
oferece uma construção denominada
interface:
Define um conjunto de métodos públicos e
abstratos correlacionados.
Pode incluir constantes.
14/10/2015 (C) 2015, Jandl. 11
Interface Reversible
Propósito: definir características comuns (uma
interface) para objetos que podem/devem ser
representados de trás-para-frente.
Operações:
▪ getElement(int) - retorna o elemento da posição dada;
▪ isReversed() - retorna true se o elemento está invertido;
▪ length() - retorna o número de elementos presentes;
▪ reverse() – inverte a sequência de elementos do objeto;
▪ toString() – retorna representação textual do objeto.
14/10/2015 (C) 2015, Jandl. 12
7. 14/10/2015
7
Exemplo
package jandl.j8i;
public interface Reversible {
char SEPARATOR =',';
Object getElement(int p);
boolean isReversed();
int length();
Reversible reverse();
String toString();
}
14/10/2015 (C) 2015, Jandl. 13
Métodos são
implicitamente
public abstract
Campos são
implicitamente
public static final
14/10/2015 (C) 2015, Jandl. 14
8. 14/10/2015
8
Por si só, a definição de uma interface não
tem utilidade.
Aplicação efetiva se dá por meio de classes
que realizam ou implementam uma
interface:
Classe inclui implementação (código) dos
métodos definidos na interface realizada
(segue o contrato).
Classe pode realizar múltiplas interfaces.
14/10/2015 (C) 2015, Jandl. 15
É como herança
múltipla!
Exemplo
package jandl.j8i;
publicclass ReversibleStringimplements Reversible{
private StringBuilder content;
private booleaninverted;
public ReversibleString(String content) {
if (content == null) throw new IllegalArgumentException("content==null");
this.content = new StringBuilder(content);
inverted = false;
}
@Override public Object getElement(intp) { return content.charAt(p); }
public String getText() { return content.toString(); }
@Override public booleanisReversed(){ return inverted; }
@Override public int length() { return content.length(); }
@Override
public Reversible reverse(){
content.reverse();
inverted = !inverted;
return this;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for(int p=0; p<content.length(); p++) {
sb.append(content.charAt(p));
if (p<content.length()-1) sb.append(SEPARATOR);
}
return sb.toString();
}
}
14/10/2015 (C) 2015, Jandl. 16
Métodos
sobrepostos
atendem interface
Elementos
adicionais podem
ser incluídos
9. 14/10/2015
9
Classe ReversibleString
representa uma cadeia
de caracteres reversível.
Caso não implemente
todos os métodos da
interface, será
considerada uma classe
abstrata.
14/10/2015 (C) 2015, Jandl. 17
<interface>
Reversible
ReversibleString
Object
Uso:
// declaração de objeto
ReversibleString rs;
// instanciação
rs = new ReversibleString(”Java");
// exibição
System.out.println(rs);
// reversão
rs.reverse();
// reexibição
System.out.println(rs.toString());
Polimorfismo:
Object o = rs;
System.out.println(o.toString())
Reversible r = rs;
rs.reverse();
14/10/2015 (C) 2015, Jandl. 18
<interface>
Reversible
ReversibleString
Object
10. 14/10/2015
10
Muitas classes podem realizar uma mesma
interface.
A interface constitui um elo comum entre tais
implementações.
Classe IntArray é outra possibilidade e
representa um arranjo reversível de valores
inteiros que também realiza a interface
Reversible.
14/10/2015 (C) 2015, Jandl. 19
Exemplo
package jandl.j8i;
publicclass IntArray implements Reversible{
private int[] value;
private booleaninverted;
public IntArray(int tam) {
value = new int[tam];
inverted = false;
}
public IntArray(int...valor) {
this.value = new int[valor.length];
for (int i = 0; i < valor.length; i++) {
this.value[i]= valor[i];
}
inverted = false;
}
@Override public Object getElement(intp) { return value[p]; }
@Override public booleanisReversed(){ return inverted; }
@Override public int length() { return value.length; }
@Override
public Reversible reverse(){
for (int i = value.length / 2 - 1; i >= 0; i--) {
int aux = value[i];
value[i] = value[value.length - 1 - i];
value[value.length- 1 - i] = aux;
}
inverted = !inverted;
return this;
}
public void setValor(int p, int v) { value[p] = v; }
@Override public String toString() {
:
return sb.toString();
}
}
14/10/2015 (C) 2015, Jandl. 20
Métodos
sobrepostos
atendem interface
Elementos
adicionais podem
ser incluídos
11. 14/10/2015
11
14/10/2015 (C) 2015, Jandl. 21
<interface>
Reversible
ReversibleString
Object
IntArray
ReversibleString e
IntArray
compartilham de
dupla herança.
Exemplo
import jandl.j8i.IntArray;
import jandl.j8i.Reversible;
import jandl.j8i.ReversibleString;
public class Teste {
public static void main(String[] args) {
ReversibleString rs = new ReversibleString("Peter Jandl
Junior");
testaReversao(rs);
IntArray arranjo = new IntArray(20, 15, 8, 30);
testaReversao(arranjo);
arranjo.reverse();
}
public static void testaReversao(Reversible r) {
for(int i=0; i<2; i++) {
System.out.println(r + ":" + r.isReversed());
r.reverse();
}
System.out.println(r + ":" + r.isReversed());
}
}
14/10/2015 (C) 2015, Jandl. 22
Método pode
manipular qualquer
objeto que realiza
interface indicada
Objetos distintos
que realizam
interface Reversible
12. 14/10/2015
12
14/10/2015 (C) 2015, Jandl. 23
Existem circunstâncias onde uma interface
deve ser modificada para acompanhar a
evolução do projeto.
Estratégia direta é definir uma sub-interface:
Herança permite que interfaces
existentes sejam estendidas em sub-interfaces.
Possibilita o reuso das definições existentes e
também a adição de novas operações.
14/10/2015 (C) 2015, Jandl. 24
13. 14/10/2015
13
Interface Reversible poderia evoluir como
Reversible2:
package jandl.j8i;
public interface Reversible2 extends Reversible {
String toStringUnreversed(Reversible r);
}
14/10/2015 (C) 2015, Jandl. 25
Reversible2 adiciona o
método toStringUnreversed
às definições de Reversible
Novas classes podem optar pela
implementação de Reversible ou
Reversible2.
Alternativa de criação de sub-interface é
simples e adequada para muitos casos
Mas …
Não resolve casos onde se torna necessário
adicionar uma operação em uma interface
existente.
14/10/2015 (C) 2015, Jandl. 26
14. 14/10/2015
14
Até Java 7 a adição de novas operações em
interface existente cria problema sério:
Todas as classes que realizam a interface alterada
devem ser modificadas para incluir novas
operações.
Se não forem modificadas, tornam-se abstratas e
não podem ser instanciadas.
Nos dois casos ocorre a propagação do problema
da interface para classes que a utilizam.
14/10/2015 (C) 2015, Jandl. 27
Java 8 soluciona questão da adição de novas
operações em interfaces existentes por meio
dos métodos de extensão:
Métodos Default
Métodos Estáticos
14/10/2015 (C) 2015, Jandl. 28
15. 14/10/2015
15
A partir do Java 8 uma interface pode conter
uma ou mais implementações de métodos
para definir as novas operações desejadas.
Tais métodos devem ser declarados como
default.
14/10/2015 (C) 2015, Jandl. 29
Exemplo
package jandl.j8i;
public interface Reversible {
char SEPARATOR =',';
Object getElement(int p);
boolean isReversed();
int length();
Reversible reverse();
String toString();
// Método default (dotado de implementação)
default String toStringUnreversed() {
if (isReversed()) {
StringBuilder sb = new StringBuilder();
for(int p=length()-1; p>=0; p--) {
sb.append(getElement(p));
if (p>0) sb.append(SEPARATOR);
}
return sb.toString();
} else {
return toString();
}
}
}
14/10/2015 (C) 2015, Jandl. 30
Código pode
instanciar e usar
objetos, além de
fazer uso de
métodos abstratos
da própria
interface!
Métodos default
também são
implicitamente
public
16. 14/10/2015
16
Adição do método default
toStringUnreversed() na interface
Reversible não implica em qualquer
modificação nas classes ReversibleString e
IntArray (que realizam Reversible).
Este método default pode ser utilizado por
quaisquer objetos destas e de outras classes
que realizem a interface Reversible.
14/10/2015 (C) 2015, Jandl. 31
Métodos comuns (ou de instância) são
operações que podem ser executadas
apenas por meio de instâncias (objetos).
Métodos estáticos (ou de classe) podem ser
executados por meio de suas classes, sem
necessidade de instâncias, além de serem
compartilhados por todos os objetos de sua
classe.
14/10/2015 (C) 2015, Jandl. 32
17. 14/10/2015
17
A partir do Java 8 as interfaces também
podem incluir métodos estáticos.
Todas as classes que realizam tais interfaces
passam a compartilhar este métodos.
Métodos estáticos das interfaces podem ser
executados por meio de suas interfaces, sem
necessidade de instâncias.
Métodos estáticos só podem utilizar elementos
externos estáticos ou internamente instanciados.
14/10/2015 (C) 2015, Jandl. 33
Exemplo
package jandl.j8i;
public interface Reversible {
char SEPARATOR =',';
Object getElement(int p);
boolean isReversed();
int length();
Reversible reverse();
String toString();
static String toStringUnreversed(Reversible r) {
if (r.isReversed()) {
StringBuilder sb = new StringBuilder();
for(int p=r.length()-1; p>=0; p--) {
sb.append(r.getElement(p));
if (p>0) sb.append(SEPARATOR);
}
return sb.toString();
} else {
return r.toString();
} }
default String toStringUnreversed() {
if (isReversed()) {
StringBuilder sb = new StringBuilder();
for(int p=length()-1; p>=0; p--) {
sb.append(getElement(p));
if (p>0) sb.append(SEPARATOR);
}
return sb.toString();
} else {
return toString();
} } }14/10/2015 (C) 2015, Jandl. 34
Código pode
instanciar e usar
objetos, mas
apenas acessar
elementos externos
estáticos!
Métodos estáticos
também são
implicitamente
public
São poucas, mas
existem diferenças
na implementação
de métodos
estáticos e default!
18. 14/10/2015
18
Exemplo
import jandl.j8i.IntArray;
import jandl.j8i.Reversible;
import jandl.j8i.ReversibleString;
public class Teste2 {
public static void main(String[] args) {
ReversibleString rs = new ReversibleString("Java 8 Interfaces");
teste(rs);
IntArray ia = new IntArray(31, 35, 64, 68, 95);
teste(ia);
}
public static void teste(Reversible r) {
r.reverse();
System.out.println(r);
System.out.println(r.toStringUnreversed());
System.out.println(Reversible.toStringUnreversed(r));
System.out.println(r);
}
}
14/10/2015 (C) 2015, Jandl. 35
Observe as formas
de acionamento
dos métodos
estáticos e default!
14/10/2015 (C) 2015, Jandl. 36
19. 14/10/2015
19
Os métodos extensão permitem a evolução
das interfaces sem a propagação dos
problemas usuais decorrentes de sua
alteração.
A alteração de interfaces com métodos
default e estáticos garante compatibilidade
binária com suas versões antigas.
14/10/2015 (C) 2015, Jandl. 37
Java - Guia do Programador. 3ª. Edição.
Peter Jandl Junior.
Novatec. 2015.
Java -
Interfaces.http://www.tutorialspoint.com/java/java_interfaces.htm
What Is an Interface? (The JavaTutorials).
https://docs.oracle.com/javase/tutorial/java/concepts/interface.html
14/10/2015 (C) 2015, Jandl. 38
20. 14/10/2015
20
14/10/2015 (C) 2015, Jandl. 39
MonteGunung &Vulcão Bromo, Java, Indonésia.
A construção mais importante introduzida no Java 8 que incorpora
características do paradigma funcional.
14/10/2015 40(C) 2015, Jandl.
21. 14/10/2015
21
Permitem definir métodos anônimos
diretamente no local de sua utilização.
Um método/função-membro anônimo
sintetiza funcionalidade usada uma única vez.
Evita o uso de classes anônimas.
Na prática torna possível a passagem de
código para métodos ao invés de objetos.
14/10/2015 (C) 2015, Jandl. 41
É uma função anônima, i.e., método sem
nome, sem especificadores de acesso, sem
modificadores, sem indicação do tipo de
retorno e dos tipos do parâmetros*.
Declaração privilegia funcionalidade (seu
código).
14/10/2015 (C) 2015, Jandl. 42
*Quandopossível.
22. 14/10/2015
22
Consiste numa lista de parâmetros enviada
diretamente para uma expressão, cujo
resultado é retornado implicitamente:
(listaParâmetros) -> expressão
14/10/2015 (C) 2015, Jandl. 43
Lista de parâmetros
cujos valores serão
utilizados pela
expressão lambda.
Expressão que
define operações
realizadas pela
expressão lambda.
Novo operador
lambda.
Exemplos:
(x) -> 2*x + 1
(x,y) -> 3*x >= 2*y
( ) -> (int)(Math.random()*6) + 1
(a,b) -> a>b ? a : b
(p,m,h) -> 1.5*p + 1.9*m + 2.0*h
14/10/2015 (C) 2015, Jandl. 44
Função que dado o parâmetro x retorna (ou
produz) o resultado da expressão 2*x + 1.
Parâmetros p, m, h são enviados para expressão
1.5*p + 1.9*m + 2.0*h retornando seu resultado.
Função sem parâmetros que
produz o resultado da expressão
(int)(Math.random()*6+1.
23. 14/10/2015
23
Parêntesis iniciais:
São requeridos para delimitar a lista de parâmetros.
Podem ser omitidos quando existe somente um
parâmetro.
Tipos dos parâmetros:
Podem ser omitidos quando inferidos pelo compilador,
a partir do contexto de uso da expressão lambda.
Quando a inferência de tipos não é possível, devem ser
indicados como na declaração de métodos.
Diretiva return:
Expressões lambda puras não requerem uso explícito.
Expressões lambda de bloco exigem uso explícito.
14/10/2015 (C) 2015, Jandl. 45
Expressões lambda mais sofisticadas podem
incluir um bloco de código onde:
Variáveis podem ser declaradas e usadas;
Objetos podem ser instanciados e usados;
São empregadas diretivas e expressões;
Retorno de resultado explícito.
Sintaxe:
(listaParâmetros) -> { bloco_de_código }
14/10/2015 (C) 2015, Jandl. 46
24. 14/10/2015
24
Exemplo
// retorna a soma dos elementos do array entre
// as posições sp (incluída) e ep (não incluída).
(double[] array, int sp, int ep) -> {
double total = 0;
for(int i=sp; i<ep; i++) {
total =+ array[i];
}
return total;
}
14/10/2015 (C) 2015, Jandl. 47
Os tipos dos parâmetros foram indicados
para exemplificar sintaxe. Isto só é
requerido quando compilador não
consegue inferir tais tipos.
Expressão lambda
constituída de bloco de
código.
Retorno explícito
do resultado da
expressão.
14/10/2015 (C) 2015, Jandl. 48
25. 14/10/2015
25
Métodos são descritos por meio de sua
assinatura, isto é, combinação de:
Tipo de retorno;
Nome; e
Lista dos tipos dos parâmetros
Expressões lambda são, analogamente,
descritas por um target-type ou tipo-alvo com:
Tipo de retorno e
Lista dos tipos dos parâmetros.
14/10/2015 (C) 2015, Jandl. 49
Exemplos de assinaturas de métodos:
Math.pow double pow (double,double)
String.length int length (void)
Long.parseLong long parseLong(String,int)
Exemplo de target-type de lambdas:
(x) -> 2*x + 1 int (int)
double (double)
(x,y) -> x >2*y boolean (double,double)
( ) -> Math.PI/2 double (void)
(s) -> s.charAt(2) char (String)
14/10/2015 (C) 2015, Jandl. 50
Depende do contexto
de uso (do tipo efetivo
do parâmetro x).
26. 14/10/2015
26
Conhecimento dos target-type permite:
Determinar onde lambdas podem ser
empregadas.
Orientar a construção de expressões compatíveis
com necessidades específicas.
Aplicação de expressões lambda requer
conhecimento sobre as interfaces funcionais
pré-definidas na API e também como
construir novas interfaces funcionais.
14/10/2015 (C) 2015, Jandl. 51
14/10/2015 (C) 2015, Jandl. 52
27. 14/10/2015
27
São aquelas que possuem um único método
abstrato em suas declarações.
Já existiam antes do Java 8 sob o nome
de single abstract methods (SAM) interfaces.
Nova denominação direciona o uso das
expressões lambda (construções típicas do
paradigma de programação funcional).
14/10/2015 (C) 2015, Jandl. 53
Exemplo
package jandl.j8l;
@FunctionalInterface
public interface Filter {
boolean accept(Student s);
}
14/10/2015 (C) 2015, Jandl. 54
Nova anotação para
designar interface
funcional.
Pode existir qualquer
número de métodos de
extensão adicionais.
Apenas um método
abstrato pode ser
incluído numa
interface funcional.
28. 14/10/2015
28
Interface Filter define um método
boolean accept (Student)
cujo objetivo é validar um objeto do tipo
Student, verificando se atende ou não algum
critério específico.
Classe Student representa um estudante por
meio de seu registro acadêmico, nome e
(código do) curso.
14/10/2015 (C) 2015, Jandl. 55
Exemplo
package jandl.j8l;
public class Student {
// campos para atributos do tipo
private long sId;
private String name;
private int course;
// construtor
public Student(long sId, String name, int course) {
this.sId = sId;
this.name = name;
this.course = course;
}
// métodos getter públicos
public long getSID() { return sId; }
public String getName() { return name; }
public int getCourse() { return course; }
// métodos setter protegidos
protected void setSID(long sId) { this.sId = sId; }
protected void setName(String name) { this.name = name; }
protected void setCourse(int course) { this.course = course; }
// representação textual
@Override
public String toString() {
return String.format("[%07d|%03d] %s", sId, course, name);
}
}
14/10/2015 (C) 2015, Jandl. 56
Classe comum para
representar uma
entidade estudante.
29. 14/10/2015
29
Exemplo
package jandl.j8l;
import java.util.ArrayList;
public class StudentDB {
// campo estático db arraylist que simula banco de dados
public staticArrayList<Student> db = newArrayList<>();
// bloco estático para inicialização do campo estático db
static {
db.add(new Student(1200001, "Bernardo Silva", 18));
db.add(new Student(1200015, "Alice Pedrosa Souza", 18));
db.add(new Student(1200348, "MiguelCosta", 18));
db.add(new Student(1300001, "Arthur Santos", 18));
db.add(new Student(1300001, "JuliaOliveira", 116));
: // e outros mais.
}
public staticArrayList<Studant> subList(Filter filter) {
// cria sublista
ArrayList<Student> result = new ArrayList<>();
// percorre todo banco de dados
for(Student s: db) {
// aplica filtro: se critério aceito, adiciona na sublista
if (filter.accept(s)) result.add(s);
}
return result; // retorna sublista
}
}
14/10/2015 (C) 2015, Jandl. 57
Um falso banco de
dados para conter
uma coleção de
estudantes.
Método que obtém
uma subconjunto
de estudantes que
atendem um
critério.
A criação de um filtro específico para objetos
do tipo Student pode ser feita por meio da
construção de uma classe que realize a
interface Filter.
Assim, a implementação do método
boolean accept (Student) pode determinar o
critério de filtragem desejado.
14/10/2015 (C) 2015, Jandl. 58
30. 14/10/2015
30
Exemplo
package jandl.j8l;
public class CourseFilterImpl
implements Filter {
@Override
public boolean accept(Student s) {
// aceita estudantes do curso 18
return s.getCourse()==18;
}
}
14/10/2015 (C) 2015, Jandl. 59
Classe
CourseFilterImpl
realiza interface Filter
com implementação
do método accept.
Método accept aceita
objetos Student cujo
curso seja 18.
Dispomos de:
Interface funcional Filter;
Classe (entidade) Student;
Classe (banco de dados) StudentDB; e
Classe (filtro específico) CourseFilterImpl.
Com estes elementos é possível testar a
filtragem de elementos provida pela classe
StudentDB com subList(Filter).
14/10/2015 (C) 2015, Jandl. 60
31. 14/10/2015
31
Exemplo
import java.util.ArrayList;
public classTeste01 {
public static void main(String[] args) {
System.out.println("Todos:");
System.out.println(StudentDB.db.toString());
ArrayList<Student> lista18 =
StudentDB.subList( new CourseFilterImpl() );
System.out.println("Curso 18:");
System.out.println(lista18.toString());
ArrayList<Student> lista2014 = StudentDB.subList(
new Filter () {
@Override
public boolean accept(Student s) {
return s.getSID()>1400000;
} }
);
System.out.println("RA>1400000:");
System.out.println(lista2014.toString());
}
}
14/10/2015 (C) 2015, Jandl. 61
Obtém sub-lista de
estudantes do curso
18, com uso do filtro
implementado como
classe independente.
Obtém sub-lista de
estudantes
ingressantes a partir de
2014, com uso do filtro
implementado como
classe anônima.
Programa de teste funciona como operado:
Método StudentDB.sublist(Filter) é bastante
conveniente.
Implementação de classe
específica/independente para filtro mostra-se
repetitiva, além de fragmentar (abstração do)
código.
Uso de classe anônima evita fragmentação do
código, evidencia critério de filtragem, mas
acrescenta complexidade e repetição ao código.
14/10/2015 (C) 2015, Jandl. 62
32. 14/10/2015
32
Exemplo
import java.util.ArrayList;
public classTeste02 {
public static void main(String[] args) {
System.out.println("Todos:");
System.out.println(StudentDB.db.toString());
ArrayList<Student> lista18 =
StudentDB.subList( new CourseFilterImpl() );
System.out.println("Curso 18:");
System.out.println(lista18.toString());
ArrayList<Student> lista2014 = StudentDB.subList(
new Filter () {
@Override
public boolean accept(Student s) {
return s.getSID()>1400000;
} }
);
System.out.println("RA>1400000:");
System.out.println(lista2014.toString());
}
}
14/10/2015 (C) 2015, Jandl. 63
Método subList requer
objeto que realize a
interface Filter.
Requisito é suprido
com instância de classe
independente que
implementa tal
interface.
Requisito é suprido
com instância de classe
anônima que realiza tal
interface.
Exemplo
import java.util.ArrayList;
public classTeste02 {
public static void main(String[] args) {
System.out.println("Todos:");
System.out.println(StudentDB.db.toString());
ArrayList<Student> lista18 =
StudentDB.subList( s -> s.getCourse() == 18 );
System.out.println("Curso 18:");
System.out.println(lista18.toString());
ArrayList<Student> lista2014 = StudentDB.subList(
s -> s.getSID()>1400000;
);
System.out.println("RA>1400000:");
System.out.println(lista2014.toString());
}
}
14/10/2015 (C) 2015, Jandl. 64
Método subList requer
objeto que realize a
interface Filter.
Lambda supre código
efetivo da interface
funcional requerida.
Lambda evidencia a
ação desejada sem
código burocrático!
33. 14/10/2015
33
14/10/2015 (C) 2015, Jandl. 65
Java 8 inclui novo pacote java.util.function
que contém a definição de muitas interfaces
funcionais de propósito geral.
Estas interfaces provêm target-types para
expressões lambda e referências de métodos.
Sua existência é mera conveniência, visto que
a definição de interfaces é um procedimento
simples.
14/10/2015 (C) 2015, Jandl. 66
34. 14/10/2015
34
A 43 interfaces existentes são organizadas
em grupos:
Function
Consumer
Supplier
Predicate
Operator
14/10/2015 (C) 2015, Jandl. 67
Consulte:
https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html
14/10/2015 (C) 2015, Jandl. 68
35. 14/10/2015
35
14/10/2015 (C) 2015, Jandl. 69
Interface Descrição
Function<T,R> Representa função que toma um argumento e produz um resultado.
BiFunction<T,U,R> Representa função que toma dois argumentos e produz um resultado.
DoubleFunction<R> Representa função que toma um argumento double e produz um resultado.
DoubleToIntFunction Representa função que toma um argumento double e produz um resultado int.
DoubleToLongFunction Representa função que toma um argumento double e produz um resultado long.
IntFunction<R> Representa função que toma um argumento int e produz um resultado.
IntToDoubleFunction Representa função que toma um argumento int e produz um resultado double.
IntToLongFunction Representa função que toma um argumento int e produz um resultado long.
LongFunction<R> Representa função que toma um argumento long e produz um resultado.
LongToDoubleFunction Representa função que toma um argumento long e produz um resultado double.
LongToIntFunction Representa função que toma um argumento long e produz um resultado int.
14/10/2015 (C) 2015, Jandl. 70
Interface Descrição
ToDoubleBiFunction<T,U>
Representa função que toma dois argumentos e produz um resultado
double.
ToDoubleFunction<T> Representa função que produz um resultado double.
ToIntBiFunction<T,U> Representa função que toma dois argumentos e produz um resultado int.
ToIntFunction<T> Representa função que produz um resultado int.
ToLongBiFunction<T,U> Representa função que toma dois argumentos e produz um resultado long.
ToLongFunction<T> Representa função que produz um resultado long.
36. 14/10/2015
36
14/10/2015 (C) 2015, Jandl. 71
14/10/2015 (C) 2015, Jandl. 72
Interface Descrição
Consumer<T> Representa operação que toma um argumento único de entrada e não retorna resultado.
BiConsumer<T,U> Representa operação que toma dois argumentos de entrada e não retorna resultado.
DoubleConsumer Representa operação que toma um único argumento double e não retorna resultado.
IntConsumer Representa operação que toma um único argumento int e não retorna resultado.
LongConsumer Representa operação que toma um único argumento long e não retorna resultado.
ObjDoubleConsumer<T> Representa operação que toma um argumento objeto e outro double e não retorna
resultado.
ObjIntConsumer<T> Representa operação que toma um argumento objeto e outro int, e não retorna
resultado.
ObjLongConsumer<T> Representa operação que toma um argumento objeto e outro long, e não retorna
resultado.
37. 14/10/2015
37
14/10/2015 (C) 2015, Jandl. 73
14/10/2015 (C) 2015, Jandl. 74
Interface Descrição
Supplier<T> Representa supridor de resultados.
BooleanSupplier Representa supridor de resultado boolean.
DoubleSupplier Representa supridor de resultados double.
IntSupplier Representa supridor de resultados int.
LongSupplier Representa supridor de resultados long.
Supplier<T> Representa supridor de resultados.
BooleanSupplier Representa supridor de resultado boolean.
DoubleSupplier Representa supridor de resultados double.
38. 14/10/2015
38
14/10/2015 (C) 2015, Jandl. 75
14/10/2015 (C) 2015, Jandl. 76
Interface Descrição
Predicate<T> Representa predicado (função boolean) de um argumento.
BiPredicate<T,U> Representa predicado (função boolean) de dois argumentos.
DoublePredicate Representa predicado (função boolean) de um argumento double.
IntPredicate Representa predicado (função boolean) de um argumento int.
LongPredicate Representa predicado (função boolean) de um argumento long.
Predicate<T> Representa predicado (função boolean) de um argumento.
BiPredicate<T,U> Representa predicado (função boolean) de dois argumentos.
DoublePredicate Representa predicado (função boolean) de um argumento double.
40. 14/10/2015
40
14/10/2015 (C) 2015, Jandl. 79
Interface Descrição
UnaryOperator<T> Representa operação sobre um operando produzindo um resultado do mesmo tipo do
operando.
BinaryOperator<T> Representa operação sobre dois operandos do mesmo tipo, produzindo um resultado do
mesmo tipo dos operandos.
DoubleBinaryOperator Representa operação sobre dois operandos double e produzindo um resultado double.
DoubleUnaryOperator Representa operação sobre um único argumento double que produz um resultado double.
IntBinaryOperator Representa operação sobre dois operandos int e produzindo um resultado int.
IntUnaryOperator Representa operação sobre um único argumento int que produz um resultado int.
LongBinaryOperator Representa operação sobre dois operandos long e produzindo resultado long.
LongUnaryOperator Representa operação sobre um único argumento long que produz um resultado long.
14/10/2015 (C) 2015, Jandl. 80
41. 14/10/2015
41
CLASSE INDEPENDENTE
public class CourseFilterImpl
implements Filter {
@Override
public boolean accept(Student s) {
return s.getCourse()==18;
}
}
EXPRESSÃO LAMBDA
s -> s.getCourse() == 18
14/10/2015 (C) 2015, Jandl. 81
CLASSE ANÔNIMA
new Filter () {
@Override
public boolean accept(Student s) {
return s.getSID()>1400000;
}
}
EXPRESSÃO LAMBDA
s -> s.getSID()>1400000
14/10/2015 (C) 2015, Jandl. 82
42. 14/10/2015
42
Substituem convenientemente o uso de
classes independentes e anônimas que
realizam interfaces funcionais.
Código claro que explicita operação desejada.
Seu uso é equivale à transferência de código.
Simplifica criação de threads, listeners do
tipo ActionListener, comparadores do tipo
Comparator<T>, entre outros usos.
14/10/2015 (C) 2015, Jandl. 83
LISTENERCONVENCIONAL
JButton button = new
JButton("Incrementar");
button.addActionListener(
new ActionListener () {
@Override
public void actionListener
(ActionEvent e) {
// incr. variável valor do escopo
valor++;
// imprime valor no console
System.out.println(”V:" + valor);
}
});
COM EXPRESSÃO LAMBDA
JButton button = new
JButton("Incrementar");
button.addActionListener( (e) -> {
// incr. variável valor do escopo
valor++;
// imprime valor no console
System.out.println(”V:" + valor);
});
14/10/2015 (C) 2015, Jandl. 84
Acesso à variáveis presentes
no escopo é denominado
captura de variáveis e não
provoca efeitos colaterais
(como closures).
43. 14/10/2015
43
THREADCONVENCIONAL
Runnable run = new Runnable () {
@Override
public void run () {
for(int i = 0; i<1000000; i++) {
// realiza alguma operação
doSomeOperation(i);
}
}
};
Thread thread = newThread(run);
thread.start();
COM EXPRESSÃO LAMBDA
Runnable run = () -> {
for(int i = 0; i<1000000; i++) {
// realiza alguma operação
doSomeOperation(i);
}
};
Thread thread = newThread(run);
thread.start();
14/10/2015 (C) 2015, Jandl. 85
14/10/2015 (C) 2015, Jandl. 86
44. 14/10/2015
44
Substituem com facilidade e clareza os
métodos abstratos de interfaces funcionais
com target-type compatíveis.
Código gerado equivale ao de classe anônima
equivalente (não há ganho, não há perda).
Isolamento provido por captura de variáveis é
outro ganho obtido com sua aplicação.
14/10/2015 (C) 2015, Jandl. 87
Java - Guia do Programador. 3ª. Edição.
Peter Jandl Junior.
Novatec. 2015.
Lambda Expressions (The JavaTutorials).
https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
When to Use Nested Classes, Local Classes,
AnonymousClasses, and Lambda Expressions
(The JavaTutorials).
https://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html
Lambda Expressions in Java 8.
http://www.drdobbs.com/jvm/lambda-expressions-in-java-8/240166764
14/10/2015 (C) 2015, Jandl. 88
45. 14/10/2015
45
14/10/2015 (C) 2015, Jandl. 89
Libélula (Dragonfly), Java, Indonésia.
Uma importante construção introduzida no Java 8 juntamente com as
expressões lambda.
14/10/2015 90(C) 2015, Jandl.
46. 14/10/2015
46
Uma referência para método é uma indicação
de que um método existente em outra classe
deve ser utilizado num ponto específico do
código.
Este mecanismo também é válido para
construtores.
14/10/2015 91(C) 2015, Jandl.
Uso de referência para método requer que
target-type do método seja compatível com
aquele requerido no local da referência.
Target-type é a combinação das informações
relativas ao tipo de retorno da expressão lambda,
seguida da lista dos tipos de seus parâmetros
entre parêntesis.
Target-type previamente definido por meio
de interface funcional.
14/10/2015 92(C) 2015, Jandl.
47. 14/10/2015
47
Compatibilidade exigida entre target-type
requerido e referência para método torna
possível:
Utilizar uma referência para método no local onde
uma expressão lambda é aceita.
Utilizar uma expressão lambda no local onde uma
referência para método é aceita.
Assim: expressões lambda e referências para
métodos tem uso intercambiável.
14/10/2015 93(C) 2015, Jandl.
Uso de referências para métodos é útil para
evitar a redefinição de métodos existentes
em outras classes.
Não interfere na possibilidade de uso de
expressões lambda.
14/10/2015 94(C) 2015, Jandl.
48. 14/10/2015
48
Referências para métodos estáticos;
Referências para métodos de instância de
objeto específico;
Referências para métodos de instância de
objeto arbitrário de tipo; e
Referências para construtores.
14/10/2015 95(C) 2015, Jandl.
14/10/2015 (C) 2015, Jandl. 96
49. 14/10/2015
49
Tipo mais simples de referência para método.
Indica um método estático com visibilidade
pública
Sintaxe:
NomeClasse::metodoEstatico
▪ NomeClasse nome da classe que contém
método estático
▪ metodoEstatico nome do método estático
14/10/2015 (C) 2015, Jandl. 97
Classe java.lang.Math possui vários métodos
públicos e estáticos:
double cbrt(double)
double exp(double)
double log(double)
Compatível com interfaces prédefinidas no
pacote java.util.function:
DoubleUnaryOperator
DoubleFunction<T>
Function<T,V>
14/10/2015 (C) 2015, Jandl. 98
Target type é
double(double)
50. 14/10/2015
50
Então, as referências para tais métodos
poderiam ser declaradas como:
DoubleUnaryOperator f_cbrt = Math::cbrt;
DoubleFunction<Double> f_exp = Math::exp;
Function<Double,Double> f_log = Math::log;
14/10/2015 (C) 2015, Jandl. 99
Função genérica
Function<tipoR,tipoP>
cujo target type é:
tipoR(tipoP)
Outros métodos da classe java.lang.Math:
double min(double,double)
double max(double,double)
double pow(double,double)
Compatível com interfaces predefinidas no
pacote java.util.function:
DoubleBinaryOperator
BinaryOperator<T>
14/10/2015 (C) 2015, Jandl. 100
Target type é
double(double,double)
51. 14/10/2015
51
Então, as referências para tais métodos
poderiam ser declaradas como:
DoubleBinaryOperator f_max = Math::max;
BinaryOperator<Double> f_min = Math::min;
Calculavel f_pow = Math::pow;
14/10/2015 (C) 2015, Jandl. 101
Toda referência para método possui uma
expressão lambda equivalente (de mesmo
target-type):
DoubleUnaryOperator
f_cbrt2 = (v) -> Math.cbrt(v);
BinaryOperator<Double>
f_min2 = (a, b) -> Math.min(a, b);
14/10/2015 (C) 2015, Jandl. 102
52. 14/10/2015
52
Uso da referência para método exige o
acionamento do método declarado pela
interface funcional e não do método
referenciado:
f_max.applyAsDouble(double, double);
f_cbrt.applyAsDouble(double);
14/10/2015 (C) 2015, Jandl. 103
Método declarado na
interface funcional
DoubleUnaryOperator
Método declarado na
interface funcional
DoubleBinaryOperator
Exemplo
package jandl.j8r;
import java.util.function.*;
public class RefMetEstatico{
public static void main(String[] args) {
//Uso direto dos métodos da classe Math
System.out.println("cbrt(27.0)="+ Math.cbrt(27.0));
System.out.println("exp(1.0)="+ Math.exp(1.0));
System.out.println("max(2.0,1.5)=" + Math.max(2.0,1.5));
System.out.println("min(2.0,1.5)=" + Math.min(2.0,1.5));
// Referências de métodos com assinatura double(double)
DoubleUnaryOperatorf_cbrt = Math::cbrt;
DoubleFunction<Double>f_exp = Math::exp;
// Referências de métodos com assinatura double(double,double)
DoubleBinaryOperatorf_max = Math::max;
BinaryOperator<Double>f_min = Math::min;
//Uso das referências de métodos
System.out.println("cbrt(27.0)="+ f_cbrt.applyAsDouble(27.0));
System.out.println("exp(1.0)="+ f_exp.apply(1.0));
System.out.println("max(2.0,1.5)=" + f_max.applyAsDouble(2.0,
1.5));
System.out.println("min(2.0,1.5)=" + f_min.apply(2.0, 1.5));
// Expressões lambda equivalentes
DoubleUnaryOperatorf_cbrt2 = v -> Math.cbrt(v);
BinaryOperator<Double>f_min2 = (a, b) -> a < b ? a : b;
//Uso das referências (de métodos) para expressões lambda
System.out.println("cbrt2(729)="+ f_cbrt2.applyAsDouble(729));
System.out.println("min2(2.0,1.5)=" + f_min2.apply(2.0, 1.5));
}
}14/10/2015 (C) 2015, Jandl. 104
53. 14/10/2015
53
14/10/2015 (C) 2015, Jandl. 105
Indica um método de instância (de um
objeto) com visibilidade pública.
Sintaxe:
objeto::metodoInstancia
▪ objeto referência válida (não nula) para
um objeto específico
▪ metodoInstancia nome do método de instância
14/10/2015 (C) 2015, Jandl. 106
54. 14/10/2015
54
Exemplo
package jandl.j8r;
public class Resistor {
protected double resistencia;
public Resistor(double resistencia) {
setResistencia(resistencia);
}
public double getResistencia() {
return resistencia;
}
public void setResistencia(double resistencia) {
if (resistencia <= 0) {
throw new RuntimeException("Resistência inválida: " + resistencia);
}
this.resistencia = resistencia;
}
public double correnteParaTensao(double tensao) {
return tensao / resistencia;
}
public double tensaoParaCorrente(double corrente) {
return resistencia * corrente;
}
@Override
public String toString() {
return String.format("R:%7.1fOhms", resistencia);
}
}
14/10/2015 (C) 2015, Jandl. 107
Classe Resistor dispõe de métodos de instância:
getResistencia(),
setResistencia(double),
correnteParaTensao(double)
tensaoParaCorrente(double)
Uma instância denominada r10k pode ser obtida com:
Resistor r10k = new Resistor(10000);
Seus métodos de instância são referenciados como:
r10K::getResistencia
r10K::setResistencia
r10K::correnteParaTensao
r10K::tensaoParaCorrente
14/10/2015 (C) 2015, Jandl. 108
55. 14/10/2015
55
Exemplo
package jandl.j8r;
import java.util.function.DoubleConsumer;
import java.util.function.DoubleFunction;
import java.util.function.DoubleSupplier;
public class RefMetInstancia {
public static void main(String[] args) {
// Instanciação de objeto tipo Resistor
Resistor resistor = new Resistor(10000);
System.out.println("Resistência: " + resistor);
// Referências para métodos da instância r10k
DoubleSupplierget_resistencia = resistor::getResistencia;
DoubleConsumerset_resistencia = resistor::setResistencia;
DoubleFunction<Double>i_V = resistor::correnteParaTensao;
DoubleFunction<Double>v_I = resistor::tensaoParaCorrente;
// Manipulação da instância via referências para métodos
System.out.println("Resistência: " + get_resistencia.getAsDouble());
System.out.println("iparaV=12V: " + i_V.apply(12));
System.out.println("vpara i=0.001A: " + v_I.apply(0.001));
set_resistencia.accept(1000);
System.out.println("NovaResistência : " + resistor);
System.out.println("Resistência: " + get_resistencia.getAsDouble());
System.out.println("iparaV=12V: " + i_V.apply(12));
System.out.println("vpara i=0.001A: " + v_I.apply(0.001));
}
}
14/10/2015 (C) 2015, Jandl. 109
Referências para
métodos de instância.
Manipulação da
instância por meio de
referências.
Referências para métodos de instância somente
afetam o objeto especificamente referenciado.
Estas referências também são equivalentes a
expressões lambda:
DoubleSupplier
get_resistencia_2 = () -> r10k.getResistencia();
DoubleConsumer
set_resistencia_2 = (r) -> r10k.setResistencia(r);
DoubleFunction<Double>
i_V_2 = (v) -> r10k.correnteParaTensao(v);
DoubleFunction<Double>
v_I_2 = (i) -> r10k.tensaoParaCorrente(i);
14/10/2015 (C) 2015, Jandl. 110
56. 14/10/2015
56
14/10/2015 (C) 2015, Jandl. 111
Indica um método de instância (de qualquer
objeto de um tipo) com visibilidade pública.
Sintaxe:
NomeClasse::metodoInstancia
▪ NomeClasse indica classe que contém método
de instância
▪ metodoInstancia nome do método de instância
14/10/2015 (C) 2015, Jandl. 112
57. 14/10/2015
57
Necessidade de ordenar objetos é comum.
Dado array de objetos Resistor:
Resistor[] resistorArray = {
new Resistor(1234), new Resistor(23456),
new Resistor(345), new Resistor(67),
new Resistor(879), new Resistor(1098),
new Resistor(543) } ;
Ordenação deste array poderia empregar:
java.util.Arrays.sort (T[], Comparator<T>)
14/10/2015 (C) 2015, Jandl. 113
Solução convencional seria construir uma
classe dotada da interface
java.util.Comparator<T> para suprir o
comparador necessário.
Tal classe deve possuir implementação que
contenha o método int compare (T a,T b)
destinado à comparar objetos para
possibilitar sua ordenação.
14/10/2015 (C) 2015, Jandl. 114
58. 14/10/2015
58
Exemplo
package jandl.j8r;
import java.util.Comparator;
// Comparador específico para objetos Resistor
public class ResistorComparator
implements Comparator<Resistor> {
@Override
public int compare(Resistor a, Resistor b) {
return (int) (a.getResistencia() - b.getResistencia());
}
}
14/10/2015 (C) 2015, Jandl. 115
Array resistorArray pode ser ordenado com:
Arrays.sort(resistorArray,
new ResistorComparator());
Opção mais simples seria utilizar um lambda
para suprir operação de comparação, pois
Comparator<T> é uma interface funcional:
Arrays.sort(resistorArray,
(Resistor a, Resistor b) —> (int) (a.getResistencia() - b.getResistencia()));
14/10/2015 (C) 2015, Jandl. 116
59. 14/10/2015
59
Outra opção seria incluir um método estático capaz
de efetuar a comparação de dois objetos do tipo
Resistor na própria classe.
public static int comparador(Resistor a, Resistor b) {
return (int) (a.getResistencia() - b.getResistencia());
}
Como target-type desse método é o mesmo do
lambda usado na ordenação do array int (Resistor,
Resistor), é possível ordenar array de tipo Resistor
com:
Arrays.sort(resistorArray, Resistor::comparador);
14/10/2015 (C) 2015, Jandl. 117
Ainda outra opção seria um método de instância
para efetuar a comparação de dois objetos do tipo
Resistor na própria classe.
public int comparador2(Resistor b) {
return (int) (this.getResistencia() - b.getResistencia());
}
Embora com assinatura int (Resistor), semântica é a
mesma de int (Resistor, Resistor), pois envolve
captura de dois objetos Resistor, assim:
Arrays.sort(resistorArray, Resistor::comparador2);
14/10/2015 (C) 2015, Jandl. 118
60. 14/10/2015
60
Exemplo
package jandl.j8r;
import java.util.Arrays;
public class RefMetTipo{
public static void main(String[] args) throws Exception {
//Array de resistores
Resistor[] resistorArray = { new Resistor(1234), new Resistor(23456),
new Resistor(345), new Resistor(67), new Resistor(879),
new Resistor(1098), new Resistor(543) };
Resistor[] copia;
System.out.println("0:"+ Arrays.toString(resistorArray));
//Ordenação do array com comparator específico
copia = resistorArray.clone();
Arrays.sort(copia,new ResistorComparator());
System.out.println("1:"+ Arrays.toString(copia));
//Ordenação do array com expressão lambda
copia = resistorArray.clone();
Arrays.sort(copia,(Resistor a, Resistor b) -> (int) (a
.getResistencia() - b.getResistencia()));
System.out.println("2:"+ Arrays.toString(copia));
//Ordenação do array com referência para método estático
copia = resistorArray.clone();
Arrays.sort(copia,Resistor::comparador);
System.out.println("3:"+ Arrays.toString(copia));
//Ordenação do array c/ referência para método de instância de tipo
copia = resistorArray.clone();
Arrays.sort(copia,Resistor::comparador2);
System.out.println("4:"+ Arrays.toString(copia));
}
}
14/10/2015 (C) 2015, Jandl. 119
Referência para
método estático.
Referência para
método de
instância.
14/10/2015 (C) 2015, Jandl. 120
61. 14/10/2015
61
Indica um construtor de com visibilidade
pública.
Sintaxe:
NomeClasse::new
▪ NomeClasse indica classe que contém
construtor
▪ new indica operação de instanciação
Como antes uso da referência para construtor
deve ser compatível com interface funcional.
14/10/2015 (C) 2015, Jandl. 121
Exemplo com classe String:
String s1 = "Java";
String s2 = new String("Java");
Fábrica de String com interface Supplier<T>:
public static Supplier<String>
StringFactory = String::new;
Uso da fábrica ao invés de instanciação direta:
String s3 = StringFactory.get();
14/10/2015 (C) 2015, Jandl. 122
62. 14/10/2015
62
Exemplo
package jandl.j8r;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
public class RefMetConstrutor {
// Método fábrica de listas de objetos do tipoT
public static <T> List<T> createList() {
return new ArrayList<T>();
}
//Supplier de listas<Resistor>
public static Supplier<List<Resistor>>resistorListFactory = ArrayList<Resistor>::new;
public static void main(String[] args) throws Exception {
//Obtenção explícita de lista
List<Long> lista1 = new ArrayList<Long>();
//Obtenção de lista com fábrica com inferência de tipo
List<Long> lista2 = RefMetConstrutor.createList();
//Obtenção de lista com Supplier
List<Resistor> lista3 = RefMetConstrutor.resistorListFactory.get();
// Uso das listas
lista1.add(123456789L);
lista1.add(135791113L);
lista2.addAll(lista1);
lista2.add(2468101214L);
lista3.add(new Resistor(10));
lista3.add(new Resistor(360));
lista3.add(new Resistor(4700));
lista3.add(new Resistor(82000));
// Exibição das listas
System.out.println("Lista1: " + lista1); System.out.println("Lista2: " + lista2);
System.out.println("Lista3: " + lista3);
}
}
14/10/2015 (C) 2015, Jandl. 123
Referência para
construtor
O uso da referência para construtor permite
alguma simplificação do código necessário,
embora o método fábrica genérico seja mais
flexível devido à possível parametrização de
tipos.
A referência para construtor é, como antes,
equivalente a uma expressão lambda:
public static Supplier<List<Long>>
listFactory = () -> newArrayList<Long>();
14/10/2015 (C) 2015, Jandl. 124
63. 14/10/2015
63
14/10/2015 (C) 2015, Jandl. 125
Java 8 tornou possível o uso de referências para
métodos existentes no lugar de expressões
lambda, desde que suas assinaturas sejam
compatíveis.
É uma alternativa interessante que permite
substituir o uso de instâncias de classes
auxiliares, instâncias de classes anônimas e até
mesmo expressões lambda pela indicação de
métodos e construtores disponíveis.
Bom uso pode reduzir a quantidade de código
necessária, simplificando o desenvolvimento de
aplicações.
14/10/2015 (C) 2015, Jandl. 126
64. 14/10/2015
64
Como para as expressões lambda, as
substituições possíveis dependem da
existência de interfaces funcionais
compatíveis.
API do Java 8 contribui com oferta de muitas
interfaces funcionais de propósito geral no
pacote java.util.function que podem servir de
target-type para lambdas e referências de
métodos.
14/10/2015 (C) 2015, Jandl. 127
Java - Guia do Programador. 3ª. Edição.
Peter Jandl Junior.
Novatec. 2015.
Method References (The JavaTutorials).
https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
Java 8 - Lambdas, Method References and
Composition.
http://www.studytrails.com/java/java8/Java8_Lambdas_FunctionalProgramming.jsp
Java Lambda Expressions vs Method
References.
https://dzone.com/articles/java-lambda-expressions-vs
14/10/2015 (C) 2015, Jandl. 128
65. 14/10/2015
65
14/10/2015 (C) 2015, Jandl. 129
Templo Prambanan, Java, Indonésia.
Nova funcionalidade do Java 8 que possibilita a realização de operações de
filtragem, mapeamento e redução no conteúdo de coleções.
14/10/2015 (C) 2015, Jandl. 130
66. 14/10/2015
66
14/10/2015 (C) 2015, Jandl. 131
Característica da linguagem Java que permite
a construção de métodos e tipos genéricos.
Uma classe ou método genérico é capaz de
operar com tipos específicos distintos
conforme sua parametrização de tipo.
Sua aplicação é flexível e, ainda assim,
garante consistência e robustez de suas
construções.
14/10/2015 (C) 2015, Jandl. 132
67. 14/10/2015
67
14/10/2015 (C) 2015, Jandl. 133
Grande conjunto de estruturas de dados de
propósito geral, na forma de conjunto de
classes e interfaces, contidas no pacote
java.util.
Utilizam os genéricos extensivamente para
permitir sua adaptação aos tipos de dados
específicos de cada problema.
14/10/2015 (C) 2015, Jandl. 134
68. 14/10/2015
68
Dentre as interfaces
principais destacam-
se:
Collection<T>
Set<T>
List<T>
Queue<T>
Map<K,V>
14/10/2015 (C) 2015, Jandl. 135
Dentre as classes (ou implementações)
principais destacam-se:
HashSet<T> conjunto
LinkedHashSet<T> conjunto
ArrayList<T> array/lista elástico
LinkedList<T> lista ligada
ArrayQueue<T> array/fila/pilha elástico
HashMap<K,V> mapa/tabela de espalha/o
TreeMap<K,V> árvore
14/10/2015 (C) 2015, Jandl. 136
69. 14/10/2015
69
14/10/2015 (C) 2015, Jandl. 137
Verifica se coleção
contém elemento
não navegado.
Retorna próximo
elemento não
navegado.
Toda e qualquer coleção pode ser navegada
com:
// obtém Iterator a partir da coleção
Iterator it = colecao.iterator();
// laço percorre e exibe elementos da coleção
while (it.hasNext()) {
System.out.println("Elemento: " + it.next());
}
A navegação das coleções numa forma
comum é possível porque:
Iterable<T> é uma superinterface de
Collection<T>.
Mecanismo provido por Iterator<T> provê:
Acesso sequencial a todos os elementos da
coleção, sem repetição;
Independência da organização da coleção;
Acesso individual aos elementos.
14/10/2015 (C) 2015, Jandl. 138
70. 14/10/2015
70
14/10/2015 (C) 2015, Jandl. 139
São dutos abstratos capazes de realizar a
transmissão de dados de uma fonte para um
destino.
Um array, uma string, um arquivo ou um dispositivo
podem funcionar como fonte dos dados, que serão
transportados pelo duto, ou como destino para
armazenar os elementos recebidos.
Praticamente todo o tratamento de arquivos e
dispositivos se baseia no uso de streams e de
suas operações de leitura (da fonte) e escrita (no
destino).
14/10/2015 (C) 2015, Jandl. 140
71. 14/10/2015
71
O novo pacote java.util.stream permite
associar um stream a uma coleção.
O conteúdo da coleção pode ser percorrido
em sequência e sem a repetição de qualquer
um de seus elementos.
Torna possível aplicar homogeneamente uma
operação específica a todo o conteúdo de
uma coleção.
Operações possíveis de transformação são a
filtragem, o mapeamento ou a redução.
14/10/2015 (C) 2015, Jandl. 141
Operação de separação de elementos
particulares de uma coleção que atendem um
critério de seleção específico:
cada elemento satisfaz um predicado pré-estabelecido.
Exemplo:
Uma coleção de objetos Automovel, que descrevem
veículos por meio de sua marca, modelo, ano de
fabricação, placa, cidade e cor.
Uma operação de filtragem poderia determinar o
conjunto de veículos de uma determinada marca, ou
de uma cidade, ou de uma combinação destes
atributos.
14/10/2015 (C) 2015, Jandl. 142
72. 14/10/2015
72
Consiste na associação de cada elemento a
uma outra informação, ou até mesmo sua
substituição por outro.
Exemplo:
Uma coleção de objetos Automovel.
Uma operação de mapeamento pode associar
informações técnicas dos modelos com seus
elementos ou substituir a placa por outro padrão
de identificação.
14/10/2015 (C) 2015, Jandl. 143
Efetua a agregação da informação contida
pelo elemento ou por um de seus atributos
produzindo um resultado final.
Exemplo:
Uma coleção de objetos Automovel.
Uma operação de redução poderia determinar a
idade média dos veículos ou a contagem daqueles
com uma cor particular.
14/10/2015 (C) 2015, Jandl. 144
73. 14/10/2015
73
Pacote java.util.stream contém interfaces e
classe que suportam o estilo funcional onde o
conteúdo de uma coleção é percorrido
sequencialmente (como num iterator).
Elementos principais:
interface BaseStream<T, S>
interface Stream<T>
interface DoubleStream
interface IntStream
interface LongStream
classe Collectors
14/10/2015 (C) 2015, Jandl. 145
Novo método forEach(Consumer<T>),
adicionado à interface Iterable<T>
(superinterface de Collection<T>), possibilita
simplificar a navegação de coleções.
Permite indicar uma função Consumer<T>
com uso de uma expressão lambda:
// exibe todos os elementos da coleção
colecao.forEach(e -> System.out.println(e));
14/10/2015 (C) 2015, Jandl. 146
74. 14/10/2015
74
Uso do método forEach(Consumer<T>) requer
um objeto que implemente a interface funcional
Consumer<T>, o que é facilmente realizado por
meio de uma expressão lambda:
Stream<Double> stream1 = lista.stream();
stream1.forEach(e -> System.out.print(e + ", "));
Navegação numa coleção por meio de um
Stream<T> é tão simples quanto com o uso de
um Iterator<T>.
14/10/2015 (C) 2015, Jandl. 147
Os streams possuem algumas características
distintas:
Não realizam o armazenamento ou retenção de
dados, pois são dutos lógicos entre um produtor e
um consumidor.
São consumíveis, ou seja, depois que um dado é
obtido, não existe possibilidade de retrocesso.
Depois de usados, devem ser descartados e
obtidos novamente para uma outra utilização.
14/10/2015 (C) 2015, Jandl. 148
75. 14/10/2015
75
Exemplo
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class StreamDemo1 {
public static void main(String[] args) {
// Cria lista com valores reais
List<Integer> lista = new ArrayList<>();
for (int i = 1; i <= 15; i++) {
lista.add((int)Math.pow(i, 2));
}
// Exibição da lista por meio de toString (implícito)
System.out.println(lista);
// Obtém stream sequencial de tipo adequado
Stream<Integer> stream1 = lista.stream();
// Uso de forEach em stream com expressão lambda
stream1.forEach(e -> System.out.print(e + ", "));
System.out.println();
// Alternativa compacta
lista.stream().forEach(e -> System.out.printf("%d; ", e));
System.out.println();
} }
14/10/2015 (C) 2015, Jandl. 149
Uso de lambdas.
Uso de streams.
14/10/2015 (C) 2015, Jandl. 150
76. 14/10/2015
76
Consiste na seleção de um subconjunto de elementos
de uma estrutura de dados ou coleção que atende a
um critério ou predicado específico.
Iterator<Double> iterator = lista.iterator();
while (iterator.hasNext()) {
// obtém elemento
double elemento = iterator.next();
// testa elemento
if (elemento > LIMITE) {
// exibe elemento > LIMITE
System.out.println(elemento);
}
}
14/10/2015 (C) 2015, Jandl. 151
Com a API provida por Stream<T> o trecho
anterior, baseado no uso de um Iterator<T>, se
reduz a:
lista.stream().filter(
elemento -> elemento > LIMITE );
Aqui ao stream associado à coleção é aplicado o
método filter(Predicate<T>), o qual é uma
interface funcional e possibilita o uso
de uma expressão lambda.
14/10/2015 (C) 2015, Jandl. 152
77. 14/10/2015
77
Exemplo
import java.util.*;
import java.util.stream.*;
public class StreamDemo2 {
public static void main(String[] args) {
//Cria lista com valores reais
List<Double>lista = newArrayList<>();
for (int i = 0; i < 180; i += 10) {
lista.add(Math.sin(Math.toRadians(i)));
}
//Uso implícitode lista.toString()
System.out.println(lista);
// Define um valor limite
doubleLIMITE = 0.95;
//Obtém stream sequencial adequado
Stream<Double>stream1 = lista.stream();
//Aplica filtro com expressão lambda
Stream<Double>maiores = stream1.filter(e -> e > LIMITE);
//Uso de forEach com expressão lambda
System.out.println("Maioresque 0.95:");
maiores.forEach(e-> System.out.println("t"+ e));
//Obtém (novamente) stream sequencial adequado
Stream<Double>stream2 = lista.stream();
//Aplica filtro com expressão lambda e adicionaem outra coleção
List<Double>menores = stream2
.filter(e -> e <= 0.2)
.collect(Collectors.toList());
//Verifica tipo do objeto retornado por Collectors
System.out.println(menores.getClass().getName());
//Uso de forEach em lista com expressão lambda
System.out.println("Menoresque 0.2:");
menores.forEach(e-> System.out.println("t"+ e));
} }
14/10/2015 (C) 2015, Jandl. 153
Uso de lambdas.
Uso de lambdas em
estilo funcional.
Uso de streams.
14/10/2015 (C) 2015, Jandl. 154
78. 14/10/2015
78
Operação de transformar elementos de uma
coleção em outros, segundo função de
mapeamento/transformação que permite
obter novo conjunto associado de valores.
Métodos existentes para isto são:
map usa Function<T>
mapToDouble usa ToDoubleFuntion<T>
mapToInt usa ToIntFunction<T>
14/10/2015 (C) 2015, Jandl. 155
Um exemplo hipotético de mapeamento:
DoubleStream resultado =
lista.stream().mapToDouble(e -> e/2.0);
Aqui é produzida a soma das metades dos
elementos obtidos por meio do stream
utilizado.
14/10/2015 (C) 2015, Jandl. 156
79. 14/10/2015
79
Exemplo
import java.util.*;
import java.util.stream.*;
public class StreamDemo3 {
public static void main(String[] args) {
//Cria lista com valores inteiros
List<Integer> lista = newArrayList<>();
for (int i = 0; i < 5; i++) lista.add(i);
System.out.println(lista);// exibe lista
//Obtém stream dos quadradosdos elementos
IntStreamquadrados= lista.stream()
.mapToInt((e)-> e * e);
quadrados.forEach((e)-> System.out.println("t"+ e));
//Cria Stream a partir de duplas de valores reais
Stream<Dupla> streamDuplas = Stream.of(newDupla(81.5, 1.69),
new Dupla(52.5, 1.62), new Dupla(64.2, 1.66));
//Obtém stream dos IMCs dos elementos com massa maior que 80
DoubleStreamimc = streamDuplas
.filter((d)-> d.valor1> 80)
.mapToDouble((d)-> d.getValor1()/Math.pow(d.valor2,2));
imc.forEach((e)-> System.out.println("[imc]" + e));
}
}
// classe utilitária
class Dupla {
public double valor1, valor2; // campos
public double getValor1() {return valor1; } // getter
public Dupla(doublevalor1, double valor2) { // construtor
this.valor1= valor1; this.valor2= valor2;
}
}
14/10/2015 (C) 2015, Jandl. 157
Uso de streams e
lambdas.
Uso de lambdas em
estilo funcional.
Uso de streams.
14/10/2015 (C) 2015, Jandl. 158
80. 14/10/2015
80
Operação que toma sequência de elementos
de entrada; aplica função de combinação em
cada um; e produz um resultado final.
Os métodos existentes para isto são:
sum
max
count
14/10/2015 (C) 2015, Jandl. 159
Exemplo
import java.util.*;
import java.util.stream.Collectors;
public class StreamDemo4 {
public static void main(String[] args) {
List<Double>listaX = new ArrayList<>();
for (double x = 0; x < 10; x+=0.5) { listaX.add(x); }
System.out.println("X:" + listaX);
Iterator<Double>iterator = listaX.iterator();
doubletotalX = 0;
while(iterator.hasNext()) {
totalX += iterator.next();
}
System.out.println("Total(X):" + totalX);
Somador somador = new Somador();
listaX.forEach(x -> somador.add(x));
System.out.println("Total(X):" + somador.getTotal());
totalX = listaX.stream()
.mapToDouble(e -> e) // mapeamento
.sum(); // redução
System.out.println("Total(X):" + totalX);
// Mapeamento restrito de X emY
List<Double>listaY = listaX.stream()
.filter(x -> x>3 && x<7) // filtragem
.map(x -> x*x -10*x +24) // mapeamento
.collect(Collectors.toList()); // coleta
System.out.println("Yrestrito:" + listaY);
//Contagem e máximo via redução predefinida
System.out.printf("Num(Yrestrito):%d valoresn",
listaY.stream().count()); // redução
Optional<Double>maxY = listaY.stream()
.max(Double::compare); // redução
System.out.println("Max(Yrestrito):" + maxY.get());
doubletotalY = listaY.stream()
.reduce(0.0, (acc, e) -> acc + e); // redução
System.out.println("Total(Yrestrito):" + totalY);
} }
class Somador { // classe utilitária
private double total;
publicSomador() { preset(0); }
publicSomador(double v) { preset(v); }
publicvoid add(double v) { total += v; }
publicdouble getTotal() {
return total; }
protected void preset( double v) {
total = v; }
publicvoid reset() { preset(0); }
}
14/10/2015 (C) 2015, Jandl. 160
Cria lista com valores reais.
(1)Totalização via
navegação com iterator.
(2)Totalização via
navegação com forEach.
(3)Totalização via redução.
(3)Totalização via redução.
(4)Totalização via redução
definida.
81. 14/10/2015
81
14/10/2015 (C) 2015, Jandl. 161
As operações em massa simplificam
enormemente a manipulação de conteúdo de
coleções, num estilo de programação funcional,
que emprega os lambda com vantagens.
As funcionalidades obtidas são em alguns casos
equivalentes ao uso de banco de dados (mas
sem o ônus de sua utilização) e, em outras
situações, são superiores, pois tratam dados que
não estão contidos em bancos de dados.
14/10/2015 (C) 2015, Jandl. 162
82. 14/10/2015
82
Java - Guia do Programador. 3ª. Edição.
Peter Jandl Junior.
Novatec. 2015.
The JavaTutorial – Lesson::Aggregate
Operations.
https://docs.oracle.com/javase/tutorial/collections/streams/
Lambdas and Streams in Java SE 8: Making
Bulk Operations simple
http://pt.slideshare.net/JAXLondon2014/lambdas-and-streams-in-java-se-8-
making-bulk-operations-simple-simon-ritter
14/10/2015 (C) 2015, Jandl. 163
14/10/2015 (C) 2015, Jandl. 164
Dançarinos Kuda-Lumping, Java, Indonésia.
83. 14/10/2015
83
Uma nova e consistente API para lidar com datas, horários e intervalos de
tempo.
14/10/2015 (C) 2015, Jandl. 165
Suporte para data e hora no Java anterior à
versão 8 era pouco intuitivo e confuso.
Elementos principais:
Classe java.util.Date [desde 1.0]
Classe java.util.Calendar [desde 1.1]
Classe java.util.GregorianCalendar [desde 1.1]
Pouca consistência entre elementos e
realidade, classes inadequadas para uso de
threads.
14/10/2015 (C) 2015, Jandl. 166
84. 14/10/2015
84
14/10/2015 (C) 2015, Jandl. 167
Java 8 inclui nova API para datas, horários e
intervalos de tempo no pacote java.time.
NovaAPI foi baseada na biblioteca JodaTime
e é centrada em três conceitos principais:
classes de valor imutável;
projeto dirigido ao domínio data-hora; e
existência de calendários diferentes.
14/10/2015 (C) 2015, Jandl. 168
85. 14/10/2015
85
Define datas, horários e intervalos com rigor,
mas de uso intuitivo.
Projetada para uso multithreaded, pois
quaisquer alterações em seus objetos gera
novos objetos, sem afetar threads que os
compartilham.
Possibilita operar calendários segundo a
ISO8601 e também outros diferentes, como
japonês, chinês ou tailandês.
14/10/2015 (C) 2015, Jandl. 169
Classes principais:
Clock
Instant
LocalDate
LocalTime
LocalDateTime
ZonedDateTime
Duration
14/10/2015 (C) 2015, Jandl. 170
86. 14/10/2015
86
14/10/2015 (C) 2015, Jandl. 171
Classe java.time.Clock permite obter um
relógio capaz de prover acesso:
ao tempo no formato UTC (UniversalTime Coordinated),
a data e horário locais (segundo fuso horário do sistema).
Um relógio pode ser obtido com método
fábrica systemUTC():
finalClock clock = Clock.systemUTC();
14/10/2015 (C) 2015, Jandl. 172
87. 14/10/2015
87
Classe java.time.Instant representa um
instante de tempo em formato UTC com
representação ISO8601.
Um relógio pode fornecer o tempo como
contagem de tempo em milissegundos
(à partir de 01/01/1970 00:00):
long agoraMillis = clock.millis();
Que equivale à:
long agoraMillis2 = System.currentTimeMillis();
14/10/2015 (C) 2015, Jandl. 173
Exemplo
package jandl.j8d;
import java.time.Clock;
import java.time.Instant;
import java.util.Date;
public class TesteClock {
public static void main(String[] args) {
// Obtém relógio
final Clock clock = Clock.systemUTC();
// Exibição de Clock
System.out.println("Clock : " + clock.instant());
System.out.println("Clock : " + clock.millis());
// Obtém instante atual como UTC usando Clock
Instant agora = clock.instant();
System.out.println("Instante: " + agora);
System.out.println("Instante: " + agora.toEpochMilli());
// Obtém instante atual como UTC usando System e Date
System.out.println("System : " +
System.currentTimeMillis());
Date data = new Date();
System.out.println("Date : " + data);
System.out.println("Date : " + data.getTime());
// Pausa de 10 segundos
try {
Thread.sleep(10000);
} catch (InterruptedException ie) {}
System.out.println();
// Reexibição de Clock, Instant, System e Date
System.out.println("Clock : " + clock.instant());
System.out.println("Clock : " + clock.millis());
System.out.println("Instante: " + agora);
System.out.println("Instante: " + agora.toEpochMilli());
System.out.println("System : " +
System.currentTimeMillis());
System.out.println("Date : " + data);
System.out.println("Date : " + data.getTime());
}
}
14/10/2015 (C) 2015, Jandl. 174
Obtém relógio UTC.
Data e hora obtidas
convencionalmente.
Obtém instante UTC.
Reexibição dos
elementos após pausa.
88. 14/10/2015
88
Exemplo Clock : 2015-09-28T15:13:32.529Z
Clock : 1443453212622
Instante: 2015-09-28T15:13:32.622Z
Instante: 1443453212622
System : 1443453212622
Date : Mon Sep 28 12:13:32 BRT 2015
Date : 1443453212623
Clock : 2015-09-28T15:13:42.648Z
Clock : 1443453222648
Instante: 2015-09-28T15:13:32.622Z
Instante: 1443453212622
System : 1443453222648
Date : Mon Sep 28 12:13:32 BRT 2015
Date : 1443453212623
14/10/2015 (C) 2015, Jandl. 175
Clock acompanha o
tempo.
Instant não
acompanha o tempo.
14/10/2015 (C) 2015, Jandl. 176
89. 14/10/2015
89
Classe java.time.LocalDate retém apenas a
informação relativa a uma data, sem
conteúdo de horário, conforme o calendário
definido pela ISO8601:
// Usando relógio local
LocalDate dataLocal = LocalDate.now();
// Usando relógio fornecido
LocalDate dataLocalClock =
LocalDate.now(clock);
14/10/2015 (C) 2015, Jandl. 177
Classe java.time.LocalTime retém apenas a
informação relativa a um horário, sem
conteúdo de data:
// Usando relógio local
LocalTime horarioLocal = LocalTime.now();
// Usando relógio fornecido
LocalTime horarioLocalClock =
LocalTime.now(clock);
14/10/2015 (C) 2015, Jandl. 178
90. 14/10/2015
90
Exemplo
package jandl.j8d;
import java.time.Clock;
import java.time.LocalDate;
import java.time.LocalTime;
public class TesteLocalDateLocalTime{
public static void main(String[] a) {
// Obtém relógio
final Clock clock = Clock.systemUTC();
// Obtém data atual local
final LocalDate dataLocal = LocalDate.now();
final LocalDate dataLocalClock = LocalDate.now(clock);
System.out.println("Data : " + dataLocal);
System.out.println("Data : " + dataLocalClock);
// Obtém horário atual local
final LocalTime horarioLocal = LocalTime.now();
final LocalTime horarioLocalClock = LocalTime.now(clock);
System.out.println("Horário: " + horarioLocal);
System.out.println("Horário: " + horarioLocalClock);
// Pausa de 2 minutos
try {
Thread.sleep(120000);
} catch (InterruptedException ie) {}
// Reexibição de data e horário local
System.out.println();
System.out.println("Data : " + dataLocal);
System.out.println("Data : " + dataLocalClock);
System.out.println("Horário: " + horarioLocal);
System.out.println("Horário: " + horarioLocalClock);
}
}
14/10/2015 (C) 2015, Jandl. 179
Obtém relógio UTC.
Obtém data local.
Reexibição dos
elementos após pausa.
Obtém horário local.
Classe java.time.LocalDateTime contém as
informações conjugadas de data e horário:
// Usando relógio local
LocalDateTime dataHoraLocal =
LocalDateTime.now();
// Usando relógio fornecido
LocalDateTime dataHoraLocalClock =
LocalDateTime.now(clock);
14/10/2015 (C) 2015, Jandl. 180
91. 14/10/2015
91
Exemplo
package jandl.j8d;
import java.time.Clock;
import java.time.LocalDateTime;
public class TesteLocalDateTime {
public static void main(String[] a) {
// Obtém relógio
final Clock clock = Clock.systemUTC();
// Obtém data e horário atual local
final LocalDateTime dataHoraLocal =
LocalDateTime.now();
final LocalDateTime dataHoraLocalClock =
LocalDateTime.now(clock);
System.out.println("DataHora: " +
dataHoraLocal);
System.out.println("DataHora: " +
dataHoraLocalClock);
}
}
14/10/2015 (C) 2015, Jandl. 181
Obtém relógio UTC.
Obtém data e
hora local.
Exibição dos
elementos.
Data específica pode ser obtida com:
LocalDate data = LocalDate.of(2015, 10, 15);
Horário específico pode ser obtido com:
LocalTime horario = LocalTime.of(13, 00, 00);
Data e horário específicos podem ser obtido
com:
LocalDateTime datahorario =
LocalDateTime.of(2015, 10, 15, 13, 00, 00);
14/10/2015 (C) 2015, Jandl. 182
92. 14/10/2015
92
Exemplo
package jandl.j8d;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class TesteFabricasDateTime {
public static void main(String[] args) {
// Data criada com método fábrica
final LocalDate republica = LocalDate.of(2015, 11, 15);
System.out.println(republica);
// Horário criado com método fábrica
final LocalTime oitoDaNoite = LocalTime.of(20, 00, 00);
System.out.println(oitoDaNoite);
//Combinação de data+hora
final LocalDateTime ldt1 = republica.atTime(oitoDaNoite);
final LocalDateTime ldt2 = oitoDaNoite.atDate(republica);
System.out.println(ldt1 + " = " + ldt2);
// Data Horário criado com método fábrica
final LocalDateTime natal =
LocalDateTime.of(2015, 12, 25, 00, 00, 00);
System.out.println(natal);
}
}
14/10/2015 (C) 2015, Jandl. 183
Cria data específica.
Combina data e hora.
Exibição dos
elementos.
Cria horário específica.
Classe java.time.ZonedDateTime contém as
informações conjugadas de data e horário para um
local específico (fuso horário):
// Usando fuso horário local
ZonedDateTime zonedDatetime =
ZonedDateTime.now();
// Usando relógio fornecido
ZonedDateTime zonedDatetimeFromClock =
ZonedDateTime.now(clock);
// Usando fuso horário indicado
ZonedDateTime zonedDatetimeFromZone1 =
ZonedDateTime.now(
ZoneId.of("America/New_York"));
14/10/2015 (C) 2015, Jandl. 184
93. 14/10/2015
93
Exemplo
package jandl.j8d;
import java.time.Clock;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class TesteZonedDateTime {
public static void main(String[] args) {
//Obtém relógio
final Clock clock =Clock.systemUTC();
//Obtém data e horário conforme fusos específicos
final ZonedDateTime zonedDatetime =
ZonedDateTime.now();
final ZonedDateTime zonedDatetimeFromClock =
ZonedDateTime.now(clock);
final ZonedDateTime zonedDatetimeFromZone1 =
ZonedDateTime.now(
ZoneId.of("America/New_York"));
final ZonedDateTime zonedDatetimeFromZone2 =
ZonedDateTime.now(
ZoneId.of("Europe/Lisbon"));
// Exibe data e horário conforme fusos específicos
System.out.println(zonedDatetime);
System.out.println(zonedDatetimeFromClock);
System.out.println(zonedDatetimeFromZone1);
System.out.println(zonedDatetimeFromZone2);
}
}
14/10/2015 (C) 2015, Jandl. 185
Obtém relógio local.
Exibição dos
elementos.
Cria data/horário do local
e com relógio dado.
Cria data/horário para
fuso específico.
14/10/2015 (C) 2015, Jandl. 186
94. 14/10/2015
94
Classe java.time.Duration representa intervalos
de tempo com o armazenamento interno da
contagem de segundos e nanosegundos.
Pode ser obtida pela diferença entre duas datas,
horários ou data-horário combinados:
// Define duas datas início e fim
Temporal inicio =
LocalDate.of(2002, Month.FEBRUARY, 20);
Temporal fim =
LocalDate.of(2015, Month.JULY, 31);
Duration duracaoIF = Duration.between(inicio, fim);
14/10/2015 (C) 2015, Jandl. 187
Intervalos maiores que a
idade estimada do universo
podem ser representados .
java.time.Temporal provê uma interface
comum para as classes LocalDate, LocalTime e
LocalDateTime que permite sua manipulação,
i.e., podem ser avançadas ou retrocedidas
temporalmente:
minus, minusYears, minusMonths, minusWeeks,
minusDays, minusHours, minusMinutes,
minusSeconds, minusNanos
plus, minusYears, plusMonths, plusWeeks, plusDays,
plusHours, plusMinutes, plusSeconds, plusNanos
asas
14/10/2015 (C) 2015, Jandl. 188
95. 14/10/2015
95
Exemplo
package jandl.j8d;
import java.time.*;
publicclass TesteDuration {
publicstatic void main(String[] args) {
// Define duas datas-horário, início e fim
final LocalDateTime inicio = LocalDateTime.of(2002,Month.FEBRUARY,20, 0, 0, 0);
final LocalDateTime fim = LocalDateTime.of(2015, Month.JULY, 31, 23, 59, 59);
// Determina intervalo entre datas fim-inicio (duração positiva)
final Duration duracaoIF = Duration.between(inicio,fim);
// Exibe intervalo e seus detalhes
System.out.printf("Duracao [%s - %s] = %sn”, fim, inicio, duracaoIF);
System.out.printf("Dias=%0,3d Horas=%0,3d Min=%0,3d Seg=%0,3dnn",
duracaoIF.toDays(), duracaoIF.toHours(),
duracaoIF.toMinutes(), duracaoIF.toMillis()/1000);
// Define nova data por meio manipulação de data existente
final LocalDateTime fimMenos10 = fim.minusDays(10);
// Determina intervalo entre datas inicio-fim (duração negativa)
final Duration duracaoFI = Duration.between(fimMenos10, inicio);
// Exibe intervalo e seus detalhes
System.out.printf("Duracao [%s - %s] = %sn", inicio, fimMenos10, duracaoFI);
System.out.printf("Dias=%0,3d Horas=%0,3d Min=%0,3d Seg=%0,3dnn",
duracaoFI.toDays(), duracaoFI.toHours(),
duracaoFI.toMinutes(), duracaoFI.toMillis()/1000);
// Define um intervalo por meio de método-fábrica
Duration dezDias = Duration.ofDays(10);
// Novo intervalo obtido pela manipulação de intervalo existente
Duration duracaoMais11 = duracaoIF.plus(dezDias).plusDays(1);
// Exibe novo intervalo
System.out.printf("Duracao + 11dias = %sn", duracaoMais11);
}
}14/10/2015 (C) 2015, Jandl. 189
Datas inicio e fim.
Define e exibe
intervalo.
Calcula e exibe intervalo
positivo.
Calcula e exibe intervalo
negativo.
Manipulação de
data.
14/10/2015 (C) 2015, Jandl. 190
96. 14/10/2015
96
Antigas classes foram mantidas para manter
a compatibilidade com aplicações
desenvolvidas antes do Java 8.
Pequena alteração foi feita na classe
java.util.Date para integrar aplicações que
usam a antiga API com a nova:
Instant Date.toInstant()
14/10/2015 (C) 2015, Jandl. 191
14/10/2015 (C) 2015, Jandl. 192
97. 14/10/2015
97
NovaAPI DateTime é um avanço substancial em
relação as antigas classes da API.
Oferecem utilização simples, consistente em
termos de sua semântica e também rigorosas
em relação ao domínio do tempo.
São imutáveis e simplificam o desenvolvimento
de aplicações multithreaded.
Recomenda-se que o desenvolvimento de novas
aplicações dê preferência ao uso da nova API.
14/10/2015 (C) 2015, Jandl. 193
Java - Guia do Programador. 3ª. Edição.
Peter Jandl Junior.
Novatec. 2015.
Trail: DateTime (The JavaTutorials).
https://docs.oracle.com/javase/tutorial/datetime/
Package java.time (Java Platform Standard
Edition 8 Documentation).
https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html
Java 8 Date/Time APITutorial.
http://examples.javacodegeeks.com/core-java/java-8-datetime-api-tutorial/
14/10/2015 (C) 2015, Jandl. 194
99. 14/10/2015
99
Adições da versão 8 são, de fato, importantes:
Métodos de extensão para interfaces
Expressões Lambda
Referências para métodos
Streams e operações em massa para coleções
NovaAPI DateTime
Paralelização de operações
Anotações melhoradas
São substanciais, podem e devem ser
aproveitadas na construção de novas
aplicações!14/10/2015 (C) 2015, Jandl. 197
Conteúdo deste
minicurso!
14/10/2015 (C) 2015, Jandl. 198