Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Java 8 - Nuevas características

1,293 views

Published on

Charla sobre las nuevas caracteristicas de Java 8, que tuvo lugar en las oficinas de MuleSoft el Jueves 12 de Junio de 2014.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Java 8 - Nuevas características

  1. 1. Java 8 Nuevas características por Fernando Petrola
  2. 2. Tópicos: 1.Interfaces funcionales 2.Expresiones Lambda 3.Stream API 4.Nuevo motor de Javascript Nashorn
  3. 3. Interfaces funcionales
  4. 4. 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
  5. 5. 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
  6. 6. • 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
  7. 7. 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”.
  8. 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); } ... }
  9. 9. 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(); } }
  10. 10. Preguntas sobre interfaces funcionales?
  11. 11. Seguimos con: Expresiones Lambda
  12. 12. 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?
  13. 13. 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
  14. 14. 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
  15. 15. Forma básica: arg -> body Forma extendida: ( T1 arg1, T2 arg2 ) -> { body } Como es una expresión lambda?
  16. 16. new InterfaceA() { public T2 method1(T1 v1) { return result; } }; v1 -> result Misma definición, diferentes expresiones
  17. 17. 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
  18. 18. ; 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=
  19. 19. Interfaces funcionales // Asignacion Predicate<String> p = String::isEmpty; // Predicate creado en contexto de la invocacion stream.filter(e -> e.getSize() > 10)... // En casteo stream.map((ToIntFunction) e -> e.getSize())... // Comparator creado con lambda String[] 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
  20. 20. • 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”:
  21. 21. 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?
  22. 22. • 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
  23. 23. 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); } }
  24. 24. 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
  25. 25. Preguntas sobre expresiones lambda?
  26. 26. Seguimos con: Stream API
  27. 27. 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.
  28. 28. Streams API Pipeline de operaciones source operation 1 operation N terminal operation.... collection array I/O channel generated 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
  29. 29. Streams API Procesamiento 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")
  30. 30. Streams API Ejemplos 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));
  31. 31. Streams API Ejemplos 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
  32. 32. 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
  33. 33. Preguntas sobre Stream API?
  34. 34. Seguimos con el: Motor de Javascript Nashorn
  35. 35. 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.
  36. 36. Motor de Javascript Nashorn Invocación desde línea de comando $ cd /usr/bin $ ln -s $JAVA_HOME/bin/jjs jjs $ jjs jjs> print('Hello World'); Archivo: hello.js var hello = function() { print("Hello Nashorn!"); }; hello(); $ jjs hello.js Hello Nashorn!
  37. 37. Motor de Javascript Nashorn Ejemplo 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);
  38. 38. Motor de Javascript Nashorn Streams 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); });
  39. 39. Motor de Javascript Nashorn Como 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();
  40. 40. Fin

×