Kit de supervivencia para Java 8 : como prepararse para Java 9
1. Kit de supervivencia para Java 8:
Como prepararse para Java 9
#FooCampRD2017
Eudris Cabrera
Junio 24, 2017
2. Eudris Cabrera
Graduado de Ingeniería Telemática en la PUCMM.
Entusiasta de la tecnología y el software libre,
desarrollador Java, instructor ocasional (Java / Linux),
aficionado del béisbol/sóftbol y los bailes latinos.
En el tiempo libre, escribe artículos, realiza charlas,
participa en eventos tecnológicos y ayuda en la revisión
de documentación técnica en el mundo Java y el código
abierto.
3. Java SE 8
Liberado en marzo del 2014, es la
plataforma que incluye la actualización
más grande para el modelo de
programación Java desde el lanzamiento
de la plataforma en 1996.
Incluye nuevas funcionalidades e
incorpora las características de los
lenguaje funcionales.
6. Tenemos una lista del tipo del tipo Team y sobre ella queremos realizar
algunas operaciones cumpliendo ciertos criterios.
public void
printTeamsHasNotWonWorldSeries(List<Team> teams){
for (Team team : teams) {
if(!team.isHasWonWoldSeries()){
System.out.println(""+ team.toString());
}
}
}
Cuáles desventajas
presenta esta solución ?
7. Ejemplo
public void printTeamsWithPredicate(List<Team> teams, Predicate<Team> tester){
for (Team t : teams) {
if(tester.test(t)){
System.out.println(""+ t.toString());
}
}
}
Predicate<Team> hasNotWonWS = new Predicate<Team>() {
@Override
public boolean test(Team t) {
return !t.isHasWonWoldSeries();
}
};
printTeamsWithPredicate(teams, hasNotWonWS);
¿Cuál es el inconveniente de
esta solución?
Las clases anónimas reduce la cantidad
de clases creadas y el paso de
comportamiento como parámetro se
mantiene, pero aún se puede detectar
mucho código repetido.
Solución usando clases anónimas
8. En nuestro ejemplo anterior, podemos utilizar una expresión lambda en
lugar de una clase anónima.
Ejemplo básico usando expresiones lambdas.
printTeamsWithPredicate(teams, (Team t) -> !t.isHasWonWoldSeries());
Nota:
Puede parecer bastante confuso en un
principio, pero ya revisaremos los
conceptos y cambios en el lenguaje que
nos permitirán escribir código Java de
esa manera.
9. Expresiones lambdas
Una expresión lambda representa una
función anónima.
λx → x+x
Función anónima que toma un número x y devuelve el resultado x + x.
10. Desarrolló en los años 30's
el "Cálculo lambda", un
sistema formal en lógica
matemática diseñado para
investigar la definición de
función, la noción de
aplicación de funciones y la
recursión.
Alonzo Church
11. Una expresión lambda se compone de un conjunto de
parámetros, un operador lambda ( -> ) y un cuerpo de la
función.
12. Sintaxis
() -> System.out.println("Hello Lambda")
x -> x + 10
(int x, int y) -> { return x + y; }
(String x, String y) -> x.length() – y.length()
(int a, int b) --> a + b
(int a) --> a + 1
(int a, int b) --> {
System.out.println(a + b);
return a + b;
}
() --> new ArrayList();
13. Expresiones Lambda abre la puerta hacia la programación funcional en Java
Funciones como entidades de primer nivel
La programación funcional establece que las
funciones (métodos) sean definidas como
entidades de primer nivel.
¿Qué
significa
eso?
Que las funciones pueden ser usada de la misma forma que usamos enteros
(integers) o cadenas de caracteres(strings).
Se pueden pasar funciones como parámetros a otras funciones y pueden ser
retornada como resultado de otras funciones.
14. Interfaces Funcionales
En Java, una interfaz funcional es, básicamente, una interfaz con un
único método abstracto.
Es la base para que podamos escribir expresiones lambda.
La interface puede tener métodos por defecto y estáticos sin que esto
afecte su condición de ser interface funcional.
Este tipo de interfaces también son conocidos como tipos SAM
(Single Abstract Method).
15. Interfaces Funcionales
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Debido a que una interfaz funcional contiene sólo un método abstracto,
puede omitir el nombre de ese método cuando se implementa.
Para ello, en lugar de utilizar una expresión de clase anónima, se utiliza
una expresión lambda.
Runnable r = () -> System.out.println("Hello Lambda");
16. Métodos Predeterminados("Default")
Tradicionalmente, las interfaces no pueden tener definiciones de método
(sólo declaraciones).
A partir de esta versión, las interfaces pueden proveer métodos con una
implementación por defecto.
Las clases que implementen dichas interfaces heredarán automáticamente
la implementación por defecto si éstas no proveen una explícitamente.
17. Métodos Predeterminados("Default")
public interface A {
default void foo() {
System.out.println("Calling A.foo()");
}
}
public class Clazz implements A {
}
public interface SaludoMananaInterface {
default void saludo(){ System.out.println("Buenos días");
}
}
18. Nuevos métodos predeterminados en interfaces existentes que
pueden utilizar Lambdas
Iterable
Iterable.forEach(Consumer c)
Collection
Collection.removeIf(Predicate p)
List
List.replaceAll(UnaryOperator o)
List.sort(Comparator c)
Reemplaza "Collections.sort(List l, Comparator c)"
19. Métodos de Referencias
Formato: target_reference::method_name
class Person {
private String name;
private int age;
public int getAge() {return this.age;}
public String getName() {return this.name;}
}
Person[] people = ...;
Comparator<Person> byName = Comparator.comparing(Person::getName);
Arrays.sort(people, byName);
Cuando una expresión lambda se compone de una sola sentencia e invoca algún método
existente por medio de su nombre, existe la posibilidad de escribirla usando métodos de
referencia, con lo cual se logra un código más compacto y fácil de leer.
20. Métodos de Referencias (Tipos)
● Método estático (ClassName::methName)
● Un método de instancia de un objeto particular
(instanceRef::methName)
● Un método super de un objeto particular (super::methName)
● Un método de instancia de un objeto arbitrario de un tipo particular
(ClassName::methName)
● Un constructor de una clase (ClassName::new)
● Un constructor de un arreglo (TypeName[]::new)
21. Nuevo paquete java.util.function
● Predicate<T> - Recibe un argumento tipo T y retorna un booleano.
● Consumer<T> - una acción que se realiza sobre un objeto
● Function<T,R> - una función que transforma un valor T a R
● Supplier<T> - provee una instancia de T (como un factory).
● UnaryOperator<T> - Forma especializada de Function. Recibe un
valor T como argumento y retorna de un valor del mismo tipo T.
● BinaryOperator<T> - Forma especializada de BiFunction. Recibe
dos argumentos y retorna un resultado, todos del mismo tipo.
22. ● Expresiones Lambdas no solo nos ayuda a escribir código más
conciso y significativo, sino que también permite simplificar la
codificación paralela.
● Métodos por defecto/estáticos en interfaces: Evolución de librerías
sin perder compatibilidad gracias a que ahora podemos definir e
implementar métodos en las interfaces.
● Simplifica como pasar comportamiento como un parámetro
(funciones como entidades de primer nivel).
● Interfaces funcionales: Concepto clave para poder escribir
expresiones lambda. Interfaces con solo un método abstracto.
Resumen sobre Expresiones Lambdas
23. Introducción al API Stream
Stream:
● Representa una abstracción para
especificar cálculos agregados
(acumulativos).
● Simplifica la descripción de los cálculos
agregados (laziness,paralelismo).
24. Elementos de un Stream
Un Stream se compone de 3 elementos:
● Un origen
● Cero o más operaciones intermedias
● Una operación final (salida o un resultado)
33. Ejemplo
Creación de un Stream vacío
Stream<String> emptyStream = Stream.empty();
long val = emptyStream.count();
Suma de arreglo de enteros
int[] numbers = {1, 2, 3, 4, 5, 6, 7};
int sum = Arrays.stream(numbers).sum();
Usando operación count
long count = Stream.of("one").count();
Convertir Stream a List
List<String> abc = Stream.of("a", "b", "c")
.collect(Collectors.toList());
Usando forEach(Consumer c)
List<Team> teams = new ArrayList<>();
teams.add(new Team("STL", "St. Louis Cardinals", true, 2011));
teams.add(new Team("NYM", "NY Mets", true, 1986));
teams.add(new Team("LAA", "LA Angels", true, 2002));
teams.add(new Team("WSN", "Washington Nationals", false, 0));
teams.add(new Team("LAD", "LA Dodgers", false, 0));
teams.forEach(p -> System.out.println(p));
34. Streams de objetos y tipos primitivos
● Java tiene valores primitivos, así como tipos de objetos.
● Para mejorar la eficiencia de Stream tenemos tres Stream de tipos
primitivos
○ IntStream, DoubleStream, LongStream
● Pueden usarse junto a los métodos mapToInt(), mapToDouble(),
mapToLong()
36. Date Time API JSR 310
Nuevo API de fecha/tiempo en java
37. Date Time API
El Date and Time API se desarrolló como parte del Java Community Process (JCP) dirigido por Stephen
Colebourne (autor de Joda-Time) y Oracle, bajo JSR 310.
El paquete java.time es el núcleo de la API y utiliza el sistema de calendario definido en ISO-8601
(https://www.iso.org/iso-8601-date-and-time-format.html ) como el calendario predeterminado.
El calendario ISO se basa en el sistema de calendario gregoriano y es el estándar internacional para
representar fecha y hora.
Para soportar las necesidades de los desarrolladores que utilizan sistemas de calendario no ISO, en
algunas áreas del mundo, como Japón o Tailandia, el nuevo API de Tiempo y Fecha permite trabajar con
diferentes sistemas de calendario.
38. java.time
LocalDate : Fecha más fácil de interpretar.
LocalDate date = LocalDate.now();
System.out.printf("%s-%s-%s", date.getYear(), date.getMonthValue(), date.getDayOfMonth());
LocalDateTime: Maneja fecha y hora sin especificar la zona horaria
LocalDateTime localDateTime = LocalDateTime.now();
ZonedDateTime zdateTime = ZonedDateTime.now(); //fecha y hora con zona horaria
Zona Horaria
ZoneId zone = ZoneId.systemDefault();
Clock clockDefault = Clock.systemDefaultZone();
ZoneId zoneAmerica = ZoneId.of("America/Santo_Domingo");
Clock clock = Clock.system(zoneAmerica);
39. java.time
Haciendo cálculo de fechas
LocalDate sinceJava8Launch = LocalDate.of(2014, Month.MARCH, 18);
LocalDate today = LocalDate.now();
today.isAfter(sinceJava8Launch); //true
Calcular diferencia entre dos fecha usando period
LocalDate sinceBarCamp2013 = LocalDate.of(2013, Month.NOVEMBER, 16);
LocalDate currentDate = LocalDate.of(2015, Month.NOVEMBER, 28);
Period betweenDates = Period.between(sinceBarCamp2013, currentDate);
int diffInDays = betweenDates.getDays();
int diffInMonths = betweenDates.getMonths();
int diffInYears = betweenDates.getYears();
40. TemporalQuery
Determinar si una fecha es festiva
usando TemporalQuery
LocalDate date = LocalDate.of(2016,
Month.JANUARY, 26);
Boolean isHoliday = date.query(new
DiasFestivosRD());
public class DiasFestivosRD implements TemporalQuery<Boolean>{
static List<MonthDay> DIAS_FESTIVOS = Lists.newArrayList(
MonthDay.of(Month.JANUARY, 1), // Año Nuevo
MonthDay.of(Month.JANUARY, 6), // Día Santos Reyes
MonthDay.of(Month.JANUARY, 21), // Día de la Altagracia
MonthDay.of(Month.JANUARY, 26), // Día del Natalicio de Duarte
MonthDay.of(Month.FEBRUARY, 27), // Día Independencia Nacional
MonthDay.of(Month.MAY, 1), //Día Trabajador
MonthDay.of(Month.AUGUST, 16), //Día Restauración
MonthDay.of(Month.SEPTEMBER, 24), //Día de las Mercedes
MonthDay.of(Month.NOVEMBER, 6), //Día Constitución
MonthDay.of(Month.DECEMBER, 25) //Día de Navidad
);
@Override
public Boolean queryFrom(TemporalAccessor date) {
MonthDay diaMesActual = MonthDay.from(date);
return DIAS_FESTIVOS.contains(diaMesActual);
}
}
41. TemporalQuery
Determinar si una fecha es esta dentro de la temporada ciclónica
LocalDate date = LocalDate.of(2017, Month.JUNE, 30);
Boolean esTemporadaCiclonica = date.query(new TemporadaCiclonica());
public class TemporadaCiclonica implements TemporalQuery<Boolean>{
@Override
public Boolean queryFrom(TemporalAccessor temporal) {
LocalDate fecha = LocalDate.from(temporal);
MonthDay primeroJulio = MonthDay.of(Month.JUNE.getValue(), 1);
MonthDay trentaNoviembre = MonthDay.of(Month.NOVEMBER.getValue(), 30);
return fecha.isAfter(primeroJulio.atYear(fecha.getYear())) &&
fecha.isBefore(trentaNoviembre.atYear(fecha.getYear()));
}
}
42.
43.
44. Sistema Modular - Proyecto Jigsaw
Es la principal novedad en Java 9.
La idea de un sistema modular es hacer el jdk más ligero para dispositivos pequeños.
El sistema de módulos proporcionará a la aplicación la capacidad de utilizar sólo los
módulos del jdk que sean necesarios.
Las aplicaciones ya no necesitarán el jdk completo. El sistema de
módulos encapsula las clases públicas dentro de un módulo. Así
que clase definida pública no estaría disponible para el mundo
entero hasta que un módulo lo defina explícitamente.
45. Sistema Modular - Proyecto Jigsaw
Los módulos van a ser descritos en un archivo llamado module-info.java ubicado en la
parte superior de la jerarquía de código java.
El archivo module-info provee:
1. Nombre del módulo.
2. Lista de dependencias de módulos necesarias para la correcta compilación y
ejecución.
3. Información sobre paquetes exportados por este módulo.
4. Lista de servicios que proporciona el módulo en tiempo de ejecución.
47. Sistema Modular - Proyecto Jigsaw
com.example.samplemodule : es el nombre del módulo.
requires : Indica que son dependencia del módulo
exports : Todas las clases públicas en estos paquetes serán accesibles a otros módulos
que dependen de él.
uses : Para usar datos de otros módulos.
provides : Proporciona configuración al servicio de otro módulo
49. Sistema Modular - Proyecto Jigsaw
Crear un jar a partir de módulo
$ jar -c -f com.eudriscabrera.examples.greetings.jar -C com.eudriscabrera.examples.greetings .
50. JShell - Java 9 REPL
Un REPL (Read-Eval-Print Loop) es una herramienta de línea de
comandos para la ejecución de sentencias de forma rápida.
51. Métodos Privados en Interfaces
Además de los métodos default "predeterminados", ahora en
Java 9 puede declarar métodos privados.
La idea es poder ocultar aquellas implementaciones de métodos
que no tienen que ser expuesta a las clases que implementen la
interfaz.
58. Asuntos Legales
Todas las marcas registradas, así como todos los
logotipos, imágenes, fotografías, audio y vídeos
mostrados en esta presentación son propiedad de
sus respectivos propietarios y/o representantes.
Su utilización es solamente para fines ilustrativos.