Java8

6,477 views

Published on

Uno de los nuevos componentes mas importantes de la próxima versión de Java es el soporte a nivel lenguaje de expresiones lambda (conocidas también como funciones anónimas o clausuras). El objetivo de la plática es de conocer el soporte para expresiones lambda en Java 8 y las ventajas y mejoras que trae consigo al lenguaje.

Los puntos que se discutirían en la plática son:

Breve introducción a la programación funcional
Porque debe interesarnos la programación funcional
Sintaxis de expresiones lambda en Java
Ventajas de las expresiones lambda
Comprativa de código de Java 7 con Java 8
Mejoras en APIs existentes (Collections)

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,477
On SlideShare
0
From Embeds
0
Number of Embeds
5,363
Actions
Shares
0
Downloads
51
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Java8

  1. 1. Programación Funcional en Java 8 Por: Ing. Sergio Rubén Irigoyen Guerra
  2. 2. Historia
  3. 3. Historia ● Clases Internas Anónimas JButton button = new Jbutton("Haga click aquí."); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ System.out.println("Click."); } });
  4. 4. Historia ● Clases Internas Anónimas JButton button = new Jbutton("Haga click aquí."); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ System.out.println("Click."); } }); Clase interna anónima
  5. 5. Historia ● Clases Internas Anónimas JButton button = new Jbutton("Haga click aquí."); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ System.out.println("Click."); } }); Sintaxis difícil de manejar Clase interna anónima
  6. 6. Historia ● Clases Internas Anónimas JButton button = new Jbutton("Haga click aquí."); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ System.out.println("Click."); } }); Sintaxis difícil de manejar Clase interna anónima Problema de “verticalidad”
  7. 7. Interfaces Funcionales
  8. 8. Interfaces Funcionales ● Una interfaz que tiene exactamente un método abstracto
  9. 9. Interfaces Funcionales ● Una interfaz que tiene exactamente un método abstracto – Runnable – Comparator – Comparable – ActionListener – EventHandler
  10. 10. Interfaces Funcionales public interface Runnable { public abstract void run(); }
  11. 11. Interfaces Funcionales Nueva anotación en Java 8 @FunctionalInterface public interface Runnable { public abstract void run(); }
  12. 12. Interfaces Funcionales Nueva anotación en Java 8 No es necesaria, pero es útil @FunctionalInterface public interface Runnable { public abstract void run(); }
  13. 13. Expresiones Lambda
  14. 14. Expresiones Lambda () ­> {}; Parámetros de entrada
  15. 15. Expresiones Lambda () ­> {}; Parámetros de entrada Bloque de código
  16. 16. Expresiones Lambda Un sólo parámetro (String s) ­> {}; (String s, Algo c) ­> {};
  17. 17. Expresiones Lambda Un sólo parámetro (String s) ­> {}; (String s, Algo c) ­> {}; Múltiples parámetros, separados por comas.
  18. 18. Expresiones Lambda Bloque de código (String s) ­> {System.out.println(s);};
  19. 19. Expresiones Lambda Bloque de código (String s) ­> {System.out.println(s);}; (String s) ­> System.out.println(s); Se pueden omitir las llaves en ciertos casos
  20. 20. Expresiones Lambda (String nombre) ­> { String saludo = "Hola " + nombre; System.out.println(saludo); } Bloque de código con múltiples instrucciones
  21. 21. Expresiones Lambda public interface Comparator<T> { int compare(T o1, T o2); } Interface Comparator
  22. 22. Expresiones Lambda Comparator<String> comp = (String s1, String s2) ­>  s1.compareTo(s2); int result = comp.compare("Argentina", "Aruba"); Implementación usando una expresión lambda
  23. 23. Expresiones Lambda Comparator<String> comp = (String s1, String s2) ­>  s1.compareTo(s2); int result = comp.compare("Argentina", "Aruba"); Usando la expresión lambda para obtener un resultado
  24. 24. Expresiones Lambda button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ System.out.println("Click."); } }); button.addActionListener((ActionEvent e) ­>  System.out.println("Click."));
  25. 25. Expresiones Lambda button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ System.out.println("Click."); } Clase interna }); anónima button.addActionListener((ActionEvent e) ­>  System.out.println("Click.")); Expresión lambda
  26. 26. Inferencia de Tipos
  27. 27. Inferencia de Tipos button.addActionListener((ActionEvent e) ­>  System.out.println("Click."));
  28. 28. Inferencia de Tipos button.addActionListener((ActionEvent e) ­>  System.out.println("Click.")); button.addActionListener(e ­>  System.out.println("Click."));
  29. 29. Inferencia de Tipos button.addActionListener((ActionEvent e) ­>  System.out.println("Click.")); Tipo Inferido button.addActionListener(e ­>  System.out.println("Click."));
  30. 30. Inferencia de Tipos button.addActionListener((ActionEvent e) ­>  System.out.println("Click.")); Tipo Inferido button.addActionListener(e ­>  System.out.println("Click.")); Se pueden omitir los paréntesis
  31. 31. Inferencia de Tipos Comparator<String> comp = (String s1, String s2) ­>  s1.compareTo(s2); Comparator<String> comp = (s1, s2) ­> s1.compareTo(s2);
  32. 32. Inferencia de Tipos Comparator<String> comp = (String s1, String s2) ­>  s1.compareTo(s2); Tipos Inferidos Comparator<String> comp = (s1, s2) ­> s1.compareTo(s2);
  33. 33. Alcance léxico
  34. 34. Alcance léxico public class ScopeTest {     public static void main(String[] args) {         ScopeTest j = new ScopeTest();         j.hacer();     }     public void hacer() {         Runnable r = () ­> System.out.println(toString());          r.run();         Runnable r2 = new Runnable() {             @Override             public void run() {                 System.out.println(toString());             }         };         r2.run();     }          @Override     public String toString(){         return "Test";     } }
  35. 35. Alcance léxico public class ScopeTest {     public static void main(String[] args) {         ScopeTest j = new ScopeTest();         j.hacer();     }     public void hacer() {         Runnable r = () ­> System.out.println(toString());          r.run();         Runnable r2 = new Runnable() {             @Override             public void run() {                 System.out.println(toString());             }         }; Imprime         r2.run(); “ScopeTest$1@5acf9800”     }          @Override     public String toString(){         return "Test";     } }
  36. 36. Alcance léxico public class ScopeTest {     public static void main(String[] args) {         ScopeTest j = new ScopeTest();         j.hacer();     }     public void hacer() {         Runnable r = () ­> System.out.println(toString());          r.run();         Runnable r2 = new Runnable() { Imprime             @Override “Test”             public void run() {                 System.out.println(toString());             }         }; Imprime         r2.run(); “ScopeTest$1@5acf9800”     }          @Override     public String toString(){         return "Test";     } }
  37. 37. Referencias a métodos
  38. 38. Referencias a métodos public abstract void run(); public static void imprime(){ System.out.println("Funciona"); }
  39. 39. Referencias a métodos public abstract void run(); Mismo tipo Imprime de“Test” retorno public static void imprime(){ System.out.println("Funciona"); }
  40. 40. Referencias a métodos public abstract void run(); Mismo tipo Imprime de“Test” retorno Mismos parámetros public static void imprime(){ System.out.println("Funciona"); }
  41. 41. Referencias a métodos public abstract void run(); Mismo tipo Imprime de“Test” retorno Mismos parámetros public static void imprime(){ System.out.println("Funciona"); } le atib p om c rma Fi
  42. 42. Referencias a métodos public class MethodReferenceTest { public static void main(String[] args) { Runnable r2 = MethodReferenceTest::imprime; r2.run(); } public static void imprime(){ System.out.println("Funciona"); } }
  43. 43. Referencias a métodos public class MethodReferenceTest { public static void main(String[] args) { Runnable r2 = MethodReferenceTest::imprime; r2.run(); } public static void imprime(){ System.out.println("Funciona"); } } Referencia a método
  44. 44. Interfaces Funcionales Predefinidas en Java 8
  45. 45. Interfaces funcionales predefinidas en Java 8 ● java.util.function – Consumer<T>  argumento tipo T y no retorna ningún resultado – Function<T, R>  argumento tipo T y retorna un resultado tipo R – Supplier<T>  sin argumentos y retorna un resultado tipo T – Predicate<T>  argumento tipo T y retorna un resultado tipo boolean
  46. 46. Métodos de extensión virtuales
  47. 47. Métodos de extensión virtuales ● Método forEach de la interfaz Iterable default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } }
  48. 48. Métodos de extensión virtuales ● Método forEach de la interfaz Iterable default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } } Método default
  49. 49. Métodos de extensión virtuales ● Método forEach de la interfaz Iterable default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } Consumer es una } Interfaz funcional
  50. 50. Métodos de extensión virtuales @FunctionalInterface public interface Predicate<T> {     boolean test(T t);     default Predicate<T> and(Predicate<? super T> other) {         Objects.requireNonNull(other);         return (t) ­> test(t) && other.test(t);     }     default Predicate<T> negate() {         return (t) ­> !test(t);     }     default Predicate<T> or(Predicate<? super T> other) {         Objects.requireNonNull(other);         return (t) ­> test(t) || other.test(t);     } }
  51. 51. Métodos de extensión virtuales @FunctionalInterface public interface Predicate<T> {     boolean test(T t); Un sólo Método abstracto     default Predicate<T> and(Predicate<? super T> other) {         Objects.requireNonNull(other);         return (t) ­> test(t) && other.test(t);     }     default Predicate<T> negate() {         return (t) ­> !test(t);     }     default Predicate<T> or(Predicate<? super T> other) {         Objects.requireNonNull(other);         return (t) ­> test(t) || other.test(t);     } }
  52. 52. Métodos de extensión virtuales @FunctionalInterface public interface Predicate<T> {     boolean test(T t);     default Predicate<T> and(Predicate<? super T> other) {         Objects.requireNonNull(other);         return (t) ­> test(t) && other.test(t);     }     default Predicate<T> negate() {         return (t) ­> !test(t);     } Métodos default     default Predicate<T> or(Predicate<? super T> other) {         Objects.requireNonNull(other);         return (t) ­> test(t) || other.test(t);     } }
  53. 53. Streams
  54. 54. Streams ● Operaciones en Streams – Terminales ● count() ● forEach()  – Intermedias ● filter()  ● distinct() 
  55. 55. Streams ● Operaciones en Streams – Terminales ● count() ● forEach()  – Intermedias ● filter()  ● distinct()  Lazy (flojas)
  56. 56. Streams ● Operaciones en Streams – – Terminales ● count() ● forEach()  Intermedias ● filter()  ● distinct()  Eager (ansiosas) Lazy (flojas)
  57. 57. Streams ● Si tenemos una lista con cien numeros entre 0 y 100, y queremos obtener la cantidad de números que sean mayores o iguales a 50 y menores a 70, podemos hacerlo de la siguiente forma usando Streams y expresiones lambda: List<Integer> numeros = new ArrayList<>(); Random rnd = new Random(); for (int i = 0; i < 100; i++) {     numeros.add(rnd.nextInt(100)); } Predicate<Integer> sm5 = s ­> s >= 50; Predicate<Integer> sm7 = s ­> s <= 70; long b = numeros.stream().filter(sm5.and(sm70)).count(); System.out.println("Resultado: " + b);
  58. 58. Streams ● Si tenemos una lista con cien numeros entre 0 y 100, y queremos obtener la cantidad de números que sean mayores o iguales a 50 y menores a 70, podemos hacerlo de la siguiente forma usando Streams y expresiones lambda: List<Integer> numeros = new ArrayList<>(); Random rnd = new Random(); for (int i = 0; i < 100; i++) {     numeros.add(rnd.nextInt(100)); } Lista con cien numeros entre 0 y 100 Predicate<Integer> sm5 = s ­> s >= 50; Predicate<Integer> sm7 = s ­> s <= 70; long b = numeros.stream().filter(sm5.and(sm70)).count(); System.out.println("Resultado: " + b);
  59. 59. Streams ● Si tenemos una lista con cien numeros entre 0 y 100, y queremos obtener la cantidad de números que sean mayores o iguales a 50 y menores a 70, podemos hacerlo de la siguiente forma usando Streams y expresiones lambda: List<Integer> numeros = new ArrayList<>(); Random rnd = new Random(); for (int i = 0; i < 100; i++) {     numeros.add(rnd.nextInt(100)); } Predicate<Integer> sm5 = s ­> s >= 50; Predicate<Integer> sm7 = s ­> s <= 70; long b = numeros.stream().filter(sm5.and(sm70)).count(); System.out.println("Resultado: " + b); Obtenemos el Stream
  60. 60. Streams ● Si tenemos una lista con cien numeros entre 0 y 100, y queremos obtener la cantidad de números que sean mayores o iguales a 50 y menores a 70, podemos hacerlo de la siguiente forma usando Streams y expresiones lambda: List<Integer> numeros = new ArrayList<>(); Random rnd = new Random(); for (int i = 0; i < 100; i++) {     numeros.add(rnd.nextInt(100)); } Predicate<Integer> sm5 = s ­> s >= 50; Predicate<Integer> sm7 = s ­> s <= 70; long b = numeros.stream().filter(sm5.and(sm70)).count(); System.out.println("Resultado: " + b); filter() recibe un Predicate como parámetro
  61. 61. Streams ● Si tenemos una lista con cien numeros entre 0 y 100, y queremos obtener la cantidad de números que sean mayores o iguales a 50 y menores a 70, podemos hacerlo de la siguiente forma usando Streams y expresiones lambda: List<Integer> numeros = new ArrayList<>(); Random rnd = new Random(); for (int i = 0; i < 100; i++) {     numeros.add(rnd.nextInt(100)); } Predicate<Integer> sm5 = i ­> i >= 50; Predicate<Integer> sm7 = i ­> i < 70; Creamos dos Predicates utilizando expresiones lambda long b = numeros.stream().filter(sm5.and(sm70)).count(); System.out.println("Resultado: " + b); filter() recibe un Predicate como parámetro
  62. 62. Streams ● Si tenemos una lista con cien numeros entre 0 y 100, y queremos obtener la cantidad de números que sean mayores o iguales a 50 y menores a 70, podemos hacerlo de la siguiente forma usando Streams y expresiones lambda: List<Integer> numeros = new ArrayList<>(); Random rnd = new Random(); for (int i = 0; i < 100; i++) {     numeros.add(rnd.nextInt(100)); } Predicate<Integer> sm5 = i ­> i >= 50; Predicate<Integer> sm7 = i ­> i < 70; long b = numeros.stream().filter(sm5.and(sm7)).count(); System.out.println("Resultado: " + b); Utilizamos el método default and() de Predicate
  63. 63. Streams ● Si tenemos una lista con cien numeros entre 0 y 100, y queremos obtener la cantidad de números que sean mayores o iguales a 50 y menores a 70, podemos hacerlo de la siguiente forma usando Streams y expresiones lambda: List<Integer> numeros = new ArrayList<>(); Random rnd = new Random(); for (int i = 0; i < 100; i++) {     numeros.add(rnd.nextInt(100)); } Predicate<Integer> sm5 = i ­> i >= 50; Predicate<Integer> sm7 = i ­> i < 70; long b = numeros.stream().filter(sm5.and(sm7)).count(); System.out.println("Resultado: " + b); Contamos el número de elementos
  64. 64. Streams ● Si tenemos una lista con cien numeros entre 0 y 100, y queremos obtener la cantidad de números que sean mayores o iguales a 50 y menores a 70, podemos hacerlo de la siguiente forma usando Streams y expresiones lambda: List<Integer> numeros = new ArrayList<>(); Random rnd = new Random(); for (int i = 0; i < 100; i++) {     numeros.add(rnd.nextInt(100)); } Predicate<Integer> sm5 = i ­> i >= 50; Predicate<Integer> sm7 = i ­> i < 70; long b = numeros.stream().filter(sm5.and(sm7)).count(); System.out.println("Resultado: " + b); Mostrar el resultado
  65. 65. Streams ● Optimización: List<Integer> numeros = new ArrayList<>(); Random rnd = new Random(); rnd.ints(100, 0, 100).forEach(numeros::add); Predicate<Integer> sm5 = i ­> i >= 50; Predicate<Integer> sm7 = i ­> i < 70; Convertir a Stream y expresiones lambda long b = numeros.stream().filter((i) ­> (i>=50 && i<70)).count(); System.out.println("Resultado: " + b);
  66. 66. Streams ● Java 7 vs Java 8: List<Integer> numeros = new ArrayList<>(); Random rnd = new Random(); for (int i = 0; i < 100; i++) { numeros.add(rnd.nextInt(100)); }       int count = 0; for (Integer i : numeros) { if(i>=50 && i<70){ count++; } } Java 7 rnd.ints(100, 0, 100).forEach(numeros::add); long b = numeros.stream().filter(i ­> i>=50 && i<70).count(); System.out.println("Resultado Java7: " + count); System.out.println("Resultado Java8: " + b);
  67. 67. Streams ● Java 7 vs Java 8: List<Integer> numeros = new ArrayList<>(); Random rnd = new Random(); for (int i = 0; i < 100; i++) { numeros.add(rnd.nextInt(100)); }       int count = 0; for (Integer i : numeros) { if(i>=50 && i<70){ count++; } } Java 7 Java 8 rnd.ints(100, 0, 100).forEach(numeros::add); long b = numeros.stream().filter(i ­> i>=50 && i<70).count(); System.out.println("Resultado Java7: " + count); System.out.println("Resultado Java8: " + b);
  68. 68. Preguntas
  69. 69. ¡Gracias!

×