Top Banner
Java 8 Nuevas características por Fernando Petrola
39

Java 8

Nov 01, 2014

Download

Documents

BVision

 
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

Java 8Nuevas características

por Fernando Petrola

Page 2: Java 8

Tópicos:

1.Interfaces funcionales

2.Expresiones Lambda

3.Stream API

4.Nuevo motor de Javascript Nashorn

Page 3: Java 8

Interfaces funcionales

Page 4: Java 8

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

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

•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

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

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

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

Preguntas sobre interfaces funcionales?

Page 11: Java 8

Seguimos con:

Expresiones Lambda

Page 12: Java 8

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

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

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

Forma básica:

arg -> body

Forma extendida:

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

Como es una expresión lambda?

Page 16: Java 8

new InterfaceA(){public T2 method1(T1 v1) { return result;}};

v1 -> result

Misma definición, diferentes expresiones

Page 17: Java 8

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

;

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

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

•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

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

•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

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

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

Preguntas sobre expresiones lambda?

Page 26: Java 8

Seguimos con:

Stream API

Page 27: Java 8

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

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

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

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

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

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

Seguimos con el:

Motor de Javascript Nashorn

Page 34: Java 8

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.

Tener en cuenta que V8 es exclusivo para JS.

Nashorn recien esta naciendo.

Page 35: Java 8

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.jsvar hello = function() { print("Hello Nashorn!");};

hello(); $ jjs hello.jsHello Nashorn!

Page 36: Java 8

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 37: Java 8

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 38: Java 8

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 39: Java 8

Fin