69
Programación Funcional en Java 8 Por: Ing. Sergio Rubén Irigoyen Guerra

Java8

Embed Size (px)

DESCRIPTION

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)

Citation preview

Page 1: Java8

Programación Funcional en Java 8

Por: Ing. Sergio Rubén Irigoyen Guerra

Page 2: Java8

Historia

Page 3: Java8

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.");}

});

Page 4: Java8

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 internaanónima

Page 5: Java8

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 internaanónima

Sintaxis difícilde manejar

Page 6: Java8

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 internaanónima

Sintaxis difícilde manejar

Problema de “verticalidad”

Page 7: Java8

Interfaces Funcionales

Page 8: Java8

Interfaces Funcionales

● Una interfaz que tiene exactamente un método abstracto

Page 9: Java8

Interfaces Funcionales

● Una interfaz que tiene exactamente un método abstracto

– Runnable

– Comparator

– Comparable

– ActionListener

– EventHandler

Page 10: Java8

Interfaces Funcionales

public interface Runnable {public abstract void run();

}

Page 11: Java8

Interfaces Funcionales

@FunctionalInterfacepublic interface Runnable {

public abstract void run();}

Nueva anotaciónen Java 8

Page 12: Java8

Interfaces Funcionales

@FunctionalInterfacepublic interface Runnable {

public abstract void run();}

Nueva anotaciónen Java 8

No es necesaria,pero es útil

Page 13: Java8

Expresiones Lambda

Page 14: Java8

Expresiones Lambda

() ­> {};

Parámetros de entrada

Page 15: Java8

Expresiones Lambda

() ­> {};

Parámetros de entrada Bloque de código

Page 16: Java8

Expresiones Lambda

(String s) ­> {};(String s, Algo c) ­> {};

Un sóloparámetro

Page 17: Java8

Expresiones Lambda

(String s) ­> {};(String s, Algo c) ­> {};

Un sóloparámetro

Múltiples parámetros,separados por comas.

Page 18: Java8

Expresiones Lambda

(String s) ­> {System.out.println(s);};

Bloque de código

Page 19: Java8

Expresiones Lambda

(String s) ­> {System.out.println(s);};(String s) ­> System.out.println(s);

Bloque de código

Se pueden omitirlas llaves en ciertos casos

Page 20: Java8

Expresiones Lambda

(String nombre) ­> {String saludo = "Hola " + nombre;System.out.println(saludo);

}

Bloque de códigocon múltiplesinstrucciones

Page 21: Java8

Expresiones Lambda

public interface Comparator<T> {int compare(T o1, T o2);

}

InterfaceComparator

Page 22: Java8

Expresiones Lambda

Comparator<String> comp = (String s1, String s2) ­> s1.compareTo(s2);

int result = comp.compare("Argentina", "Aruba");

Implementaciónusando una

expresión lambda

Page 23: Java8

Expresiones Lambda

Comparator<String> comp = (String s1, String s2) ­> s1.compareTo(s2);

int result = comp.compare("Argentina", "Aruba");

Usando la expresiónlambda para obtener

un resultado

Page 24: Java8

Expresiones Lambda

button.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e){

System.out.println("Click.");}

});

button.addActionListener((ActionEvent e) ­> System.out.println("Click."));

Page 25: Java8

Expresiones Lambda

button.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e){

System.out.println("Click.");}

});

Expresiónlambda

Clase interna anónima

button.addActionListener((ActionEvent e) ­> System.out.println("Click."));

Page 26: Java8

Inferencia de Tipos

Page 27: Java8

Inferencia de Tipos

button.addActionListener((ActionEvent e) ­> System.out.println("Click."));

Page 28: Java8

Inferencia de Tipos

button.addActionListener((ActionEvent e) ­> System.out.println("Click."));

button.addActionListener(e ­> System.out.println("Click."));

Page 29: Java8

Inferencia de Tipos

button.addActionListener((ActionEvent e) ­> System.out.println("Click."));

button.addActionListener(e ­> System.out.println("Click."));

TipoInferido

Page 30: Java8

Inferencia de Tipos

button.addActionListener((ActionEvent e) ­> System.out.println("Click."));

button.addActionListener(e ­> System.out.println("Click."));

TipoInferido

Se puedenomitir losparéntesis

Page 31: Java8

Inferencia de Tipos

Comparator<String> comp = (String s1, String s2) ­> s1.compareTo(s2);

Comparator<String> comp = (s1, s2) ­> s1.compareTo(s2);

Page 32: Java8

Inferencia de Tipos

Comparator<String> comp = (String s1, String s2) ­> s1.compareTo(s2);

Comparator<String> comp = (s1, s2) ­> s1.compareTo(s2);

TiposInferidos

Page 33: Java8

Alcance léxico

Page 34: Java8

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";    }}

Page 35: Java8

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";    }}

Imprime“ScopeTest$1@5acf9800”

Page 36: Java8

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";    }}

Imprime“Test”

Imprime“ScopeTest$1@5acf9800”

Page 37: Java8

Referencias a métodos

Page 38: Java8

Referencias a métodos

public abstract void run();

public static void imprime(){System.out.println("Funciona");

}

Page 39: Java8

Referencias a métodos

public abstract void run();

public static void imprime(){System.out.println("Funciona");

}

Imprime“Test”

Mismo tipode retorno

Page 40: Java8

Referencias a métodos

public abstract void run();

public static void imprime(){System.out.println("Funciona");

}

Imprime“Test”

Mismo tipode retorno

Mismosparámetros

Mismosparámetros

Page 41: Java8

Referencias a métodos

public abstract void run();

public static void imprime(){System.out.println("Funciona");

}

Imprime“Test”

Mismo tipode retorno

Mismosparámetros

Mismosparámetros

Firma compatible

Page 42: Java8

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");

}}

Page 43: Java8

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 amétodo

Page 44: Java8

Interfaces Funcionales Predefinidas en Java 8

Page 45: Java8

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

Page 46: Java8

Métodos de extensión virtuales

Page 47: Java8

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);}

}

Page 48: Java8

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étododefault

Page 49: Java8

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 unaInterfaz funcional

Page 50: Java8

Métodos de extensión virtuales

@FunctionalInterfacepublic 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);    }

}

Page 51: Java8

Métodos de extensión virtuales

@FunctionalInterfacepublic 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);    }

}

Un sóloMétodo

abstracto

Page 52: Java8

Métodos de extensión virtuales

@FunctionalInterfacepublic 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);    }

}

Métodos default

Métodos default

Métodos default

Page 53: Java8

Streams

Page 54: Java8

Streams

● Operaciones en Streams

– Terminales● count()● forEach() 

– Intermedias● filter() ● distinct() 

Page 55: Java8

Streams

● Operaciones en Streams

– Terminales● count()● forEach() 

– Intermedias● filter() ● distinct() 

Lazy(flojas)

Page 56: Java8

Streams

● Operaciones en Streams

– Terminales● count()● forEach() 

– Intermedias● filter() ● distinct() 

Lazy(flojas)

Eager(ansiosas)

Page 57: Java8

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);

Page 58: Java8

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);

Lista con cien numeros entre

0 y 100

Page 59: Java8

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 elStream

Page 60: Java8

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

Page 61: Java8

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(sm70)).count();

System.out.println("Resultado: " + b);

filter() recibe un Predicate como

parámetro

Creamos dos Predicatesutilizando expresiones lambda

Page 62: Java8

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 defaultand() de Predicate

Page 63: Java8

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

Page 64: Java8

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

Page 65: Java8

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;

long b = numeros.stream().filter((i) ­> (i>=50 && i<70)).count();

System.out.println("Resultado: " + b);

Convertir a Stream y expresiones lambda

Page 66: Java8

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++;

}}

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);

Java 7

Page 67: Java8

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++;

}}

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);

Java 7

Java 8

Page 68: Java8

Preguntas

Page 69: Java8

¡Gracias!