Top Banner
Java 8 Nuevas características por Fernando Petrola
40
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Java 8 - Nuevas características

Java 8Nuevas características

por Fernando Petrola

Page 2: Java 8 - Nuevas características

Tópicos:

1.Interfaces funcionales

2.Expresiones Lambda

3.Stream API

4.Nuevo motor de Javascript Nashorn

Page 3: Java 8 - Nuevas características

Interfaces funcionales

Page 4: Java 8 - Nuevas características

Functional Interface:

1. Es una Interface que tiene un solo método abstracto.

2. El annotation @FunctionalInterface se puede usar

como mecanismo de advertencia en la compilación.

3. Se suelen implementar métodos por defecto dentro.

4. Antes de crear una nueva mirar las predefinidas en

java.util.function.*

5. Los tipos de datos primitivos tienen interfaces

funcionales predefinidas específicas.

6. Son usadas en conjunto con expresiones lambdas

Page 5: Java 8 - Nuevas características

public interface ActionListener extends EventListener{

public void actionPerformed(ActionEvent e); }

public interface Callable<V> { public V call(); }

public interface Runnable

{ public void run(); }

public interface Comparator<T>

{

int compare(T o1, T o2);

boolean equals(Object obj);

}

Ejemplos de Functional Interfaces ya conocidas

Page 6: Java 8 - Nuevas características

• Supplier<T>: Devuelve un T• Consumer<T>: Recibe un T• BiConsumer<T, U>: Recibe un T y un U• Predicate<T>: Evalua un T y devuelve un boolean• Function<T, R>: Recive un T y devuelve un R• BinaryOperator<T>: Recibe 2 T y devuelve un T

Functional Interfaces

Predefinidas genéricas

• (Int | Long | Double)Supplier• (Int | Long | Double)Consumer• (Int | Long | Double)Predicate• (Int | Long | Double)Function<R>• (Int | Long | Double)BinaryOperator• Obj(Int | Long | Double)Consumer<T>• (Int | Long | Double)To(Int | Long | Double)Function

Predefinidas para primitivos

Page 7: Java 8 - Nuevas características

Functional Interfaces

Default Methods

1.Permiten definir Interfaces que tengan algo de

comportamiento.

2.Son heredados por las clases implementadoras

3.Al heredar más de una implementación del mismo método

se puede elegir cual usar en la subclase.

4.Facilitan “backward compatibility” de Collections

5.Solo interactúan con otros métodos y son “stateless”.

Page 8: Java 8 - Nuevas características

Ejemplo de default methods

public interface Predicate<T> {

boolean test(T t);

default Predicate<T> and(Predicate<? super T> other) { return (t) -> test(t) && other.test(t);}

default Predicate<T> negate() { return (t) -> !test(t);}

...}

Page 9: Java 8 - Nuevas características

Default Methods

Herencia

public interface A{

default public String foo(){ return “A”;}

}

public interface B{

default public String foo(){ return “B”;}

}

public class AB implements A, B{

public String foo(){ return B.super.foo();}

}

Page 10: Java 8 - Nuevas características

Preguntas sobre interfaces funcionales?

Page 11: Java 8 - Nuevas características

Seguimos con:

Expresiones Lambda

Page 12: Java 8 - Nuevas características

Expresiones Lambda

• Es un bloque de código

• Método anónimo

• Parecido al resultado obtenido con clases

anónimas

• Termina creando una instancia de una interfaz

funcional

Que es una expresión lambda?

Page 13: Java 8 - Nuevas características

Expresiones Lambda

• Código más compacto y limpio

• Da lugar al surgimiento de Streams API

• + declarativo, - implementativo

• Permite aplicar varias optimizaciones

• Inferencia de tipos

• Mismas reglas de scope que los bloques de código

tradicionales

• Primer paso para la inclusión de programación funcional

Ventajas

Page 14: Java 8 - Nuevas características

Expresiones Lambda

• No son funciones reales, son métodos anónimos.

• Sólo permite capturar variables inmutables y miembros

de la clase.

• No se puede declarar la firma de una “funcion” anónima:public static void runOperation((int -> int) operation) { ... }

Contras

Page 15: Java 8 - Nuevas características

Forma básica:

arg -> body

Forma extendida:

( T1 arg1, T2 arg2 ) -> { body }

Como es una expresión lambda?

Page 16: Java 8 - Nuevas características

new InterfaceA(){

public T2 method1(T1 v1) {

return result;}

};

v1 -> result

Misma definición, diferentes expresiones

Page 17: Java 8 - Nuevas características

button.addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent e) {

System.out.println(“click”);}

});

El ejemplo más esperado.. JButton!

Con clases anónimas

button.addActionListener(e -> System.out.println(“click”));

Con lambdas

Page 18: Java 8 - Nuevas características

;

BinaryOperator<Integer> sumador= new BinaryOperator<Integer>(){

public Integer apply(Integer v1, Integer v2) {

return v1 + v2;}

};

Inferencia de tipos, bloque de código, return

(Integer v1, Integer v2) -> { return v1 + v2; }

ó

(v1, v2) -> { return v1 + v2; }

ó

(v1, v2) -> v1 + v2

BinaryOperator<Integer> sumador=

Page 19: Java 8 - Nuevas características

Interfaces funcionales

// AsignacionPredicate<String> p = String::isEmpty;

// Predicate creado en contexto de la invocacionstream.filter(e -> e.getSize() > 10)...

// En casteostream.map((ToIntFunction) e -> e.getSize())...

// Comparator creado con lambdaString[] list= new String[] { "One", "Two", "Three", "Four", "Five", "Six" };Arrays.sort(list, (a, b)->a.substring(1).compareTo(b.substring(1)));

Creadas a partir de lambdas

Page 20: Java 8 - Nuevas características

• Declaración de variables• Asignaciones• Instrucción “return”• Inicializadores de Arrays• Parámetros de métodos o constructores• Cuerpo de un lambda • Condicionales (?:)• Casteos

Donde se pueden usar lambdas?

FileFilter[] filters= new FileFilter[] { f -> f.exists(), f -> f.getName().startsWith("q") };

Object o = (Runnable) () -> { System.out.println("hola"); };

Supplier<Runnable> c = () -> () -> { System.out.println("hola"); };

Callable<Integer> c = flag ? (() -> 23) : (() -> 42);

Ejemplos para destacar:

En contextos que tengan “target type”:

Page 21: Java 8 - Nuevas características

public class Hola {

Runnable r1 = () -> { System.out.println(this); } Runnable r2 = () -> { System.out.println(toString()); }

public String toString() { return "Hola mundo!"; }

public static void main(String... args) { new Hola().r1.run(); new Hola().r2.run(); } }

Como se maneja el scope?

Page 22: Java 8 - Nuevas características

• Método estático (ClassName::methName)• Método de un instancia (instanceRef::methName)• Método super de un objeto particular (super::methName)• Método de instancia de un tipo (ClassName::methName)• Constructor de clase (ClassName::new)• Constructor de arreglo (TypeName[]::new)

Otra forma de lambda: referencia a método

Collection<String> knownNames= Arrays.asList("Hello", "Java", "World", "8", "Streams");

Predicate<String> isKnown = knownNames::contains;

Function<String, String> upperfier = String::toUpperCase;

IntFunction<int[]> arrayMaker = int[]::new;

int[] array = arrayMaker.apply(10); // crea un arreglo int[10]

Ejemplos:

Tipos de referencias a metodos

Page 23: Java 8 - Nuevas características

interface Getter<O, T>{

T get(O obj);}

Funcionalidad emergente: Reflection Refactorizable!!

interface Setter<O, T>{

void set(O obj, T param);}

public class ClaseA{

int field1;public int getField1(){

return field1;}public void setField1(int field1){

this.field1= field1;}public static void main(String[] args){Getter<ClaseA, Integer> getter= ClaseA::getField1;

Setter<ClaseA, Integer> setter= ClaseA::setField1;

ClaseA obj= new ClaseA();setter.set(obj, 10);Integer value= getter.get(obj);

}}

Page 24: Java 8 - Nuevas características

Funcionalidad emergente: Reflection Refactorizable!!

public class RefactoringEnabledHibernateMapper<T>{

public RefactoringEnabledHibernateMapper(Supplier<T> supplier) {...}public <V> void setIdAccessors(Getter<T, V> getter, Setter<T, V> setter) {...}public <V> void addPropertyAccessors(Getter<T, V> getter, Setter<T, V> setter) {...}

}

RefactoringEnabledHibernateMapper<Person> mapper= new RefactoringEnabledHibernateMapper<Person>(Person::new);mapper.setIdAccessors(Person::getId, Person::setId);mapper.addPropertyAccessors(Person::getName, Person::setName);mapper.addPropertyAccessors(Person::getAge, Person::setAge);

RefactoringEnabledHibernateMapper

Page 25: Java 8 - Nuevas características

Preguntas sobre expresiones lambda?

Page 26: Java 8 - Nuevas características

Seguimos con:

Stream API

Page 27: Java 8 - Nuevas características

Streams API

• Un stream es una secuencia de elementos generada a

partir de:

• Collections

• Arrays

• Generators (on the fly)

• I/O Channels

• Los streams no guardan los elementos

• Mecanismo de procesamiento con pipeline de operaciones.

• En el procesamiento se aplican varias técnicas de

optimización.

• Las expresiones lambda le aportan mucha legibilidad.

• Provee mecanismo versátil para recolectar los resultados.

Page 28: Java 8 - Nuevas características

Streams API

Pipeline de operaciones

sourceoperation

1operation

N terminal operation....

collectionarray

I/O channelgenerated

map, filter, distinct, sorted, peek, limit, parallel, sequencial, unordered, reduce, sum, skip

forEach, toArray, reduce, collect,

min, max, count, anyMatch, allMatch,

noneMatch, findFirst, findAny,

iterator

Page 29: Java 8 - Nuevas características

Streams APIProcesamiento de un stream

.map(Integer::parseInt)

.limit(3)

.forEach(i -> System.out.println(i))

.filter(i -> i % 2 != 0)

“1”

“2”

“3”

“1”

“2”

“3”

1 2 3

1 3

“4”

“5”

Stream.of("1", "2", "3", "4", "5")

Page 30: Java 8 - Nuevas características

Streams APIEjemplos

List<Integer> numbers = Arrays.asList(9, 10, 3, 4, 7, 3, -4);

List<Integer> distinct = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());

IntStream.range(0, 100).parallel().filter(i -> i % 2 == 0).forEach(System.out::println);

List<String> G7 = Arrays.asList("USA", "Japan", "France", "Germany", "Italy", "U.K.","Canada"); String G7Countries = G7.stream().map(x -> x.toUpperCase()).collect(Collectors.joining(", "));

List names = Arrays.asList("Java", "Scala", "C++", "Haskell", "Lisp");

Predicate<String> startsWithJ = n -> n.startsWith("J");

Predicate<String> fourLetterLong = n -> n.length() == 4;

names.stream()

.filter(startsWithJ.and(fourLetterLong))

.forEach((n) -> System.out.print("Empieza con J y tiene 4 caracteres: " + n));

Page 31: Java 8 - Nuevas características

Streams APIEjemplos

Map<City, Set<String>> namesByCity= people.stream().collect(Collectors.groupingBy (

Person::getCity, Collectors.mapping (Person::getLastName, toSet())));

Resultado: Obtiene los apellidos de las personas en cada ciudad

IntStream.iterate(0, i -> i + 2).limit(5).forEach(System.out::println);

Resultado: imprime 0, 2, 4, 6, 8

Page 32: Java 8 - Nuevas características

Streams API

Name Returns Interface Lambda

signature

filter Stream<T> lazy Predicate<T> T -> boolean

map Stream<U> lazy Function<T, U> T -> U

sorted Stream<T> lazy Comparator<T> (T, T) -> int

limit Stream<T> lazy n/a n/a

skip Stream<T> lazy n/a n/a

reduce T eager BinaryOperator<T

>

(T, T) -> T

findFirst T eager n/a n/a

groupBy Map<U,

Collection<T>>

eager Function<T, U> T -> U

forEach void eager Consumer<T> T -> void

Resumen de operaciones

Page 33: Java 8 - Nuevas características

Preguntas sobre Stream API?

Page 34: Java 8 - Nuevas características

Seguimos con el:

Motor de Javascript Nashorn

Page 35: Java 8 - Nuevas características

Motor de Javascript Nashorn

1. Correr código dinámico Javascript nativo en la JVM

2. Se basa en el uso del nuevo bytecode InvokeDynamic,

presentado en Java 7

3. Soporta la especificación ECMAScript 5.1

4. De 2 a 10x la velocidad de Rhino

5. Se acerca mucho más a la performance de V8, según

algunos benchmarks llega a la mitad de velocidad.

a. Tener en cuenta que V8 es exclusivo para JS.

b. Nashorn recien esta naciendo.

Page 36: Java 8 - Nuevas características

Motor de Javascript NashornInvocación desde línea de comando

$ cd /usr/bin$ ln -s $JAVA_HOME/bin/jjs jjs$ jjsjjs> print('Hello World');

Archivo: hello.js

var hello = function() { print("Hello Nashorn!");};

hello();

$ jjs hello.jsHello Nashorn!

Page 37: Java 8 - Nuevas características

Motor de Javascript NashornEjemplo de invocación

script.js:var fun1 = function(name) { print('Hi there from Javascript, ' + name); return "greetings from javascript";};

ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");engine.eval(new FileReader("script.js"));

Invocable invocable = (Invocable) engine;Object result = invocable.invokeFunction("fun1", "Peter Parker");System.out.println(result);

Page 38: Java 8 - Nuevas características

Motor de Javascript NashornStreams

var list2 = new java.util.ArrayList();

list2.add("ddd2");

list2.add("aaa2");

list2.add("aaa3");

list2

.stream()

.filter(function(el) {

return el.startsWith("aaa");

})

.sorted()

.forEach(function(el) {

print(el);

});

Page 39: Java 8 - Nuevas características

Motor de Javascript NashornComo extender clases de Java

var Runnable = Java.type('java.lang.Runnable');

var Printer = Java.extend(Runnable, {

run: function() {

print('printed from a separate thread');

}

});

var Thread = Java.type('java.lang.Thread');

new Thread(new Printer()).start();

new Thread(function() {

print('printed from another thread');

}).start();

Page 40: Java 8 - Nuevas características

Fin