lunes, 26 de octubre de 2015

Lambdas

Lambdas



Una característica única de las interfaces funcionales es que pueden ser instanciadas usando "lambdas". Veamos algunos ejemplos de lambdas.

Una lista de entradas separada por comas, indicando el tipo de datos, y un bloque que retorna la suma de ambos parámetros:

(int x, int y) -> { return x + y; }


 Una lista de entradas separada por comas, infiriendo el tipo de datos, y retorna la suma de ambos:

(x, y) -> x + y

Un único parámetro con el tipo de dato inferido, y retorna ese parámetro al cuadrado:


x -> x * x

Sin valores de entrada, retorna un valor:

() -> x

Un único parámetro de entrada con el tipo de datos inferido, y un bloque que retorna void a la derecha:

x -> { System.out.println(x); }

También hay algunas formas "cortas" de escribir lambdas comunes:

String::valueOf             x -> String.valueOf(x)
Object::toString            x -> x.toString()
x::toString                    () -> x.toString()
ArrayList::new             () -> new ArrayList<>()

Por supuesto, en Java existe la sobrecarga de métodos. Los operadores lambda intentan usar el método que mejor se adapte a la expresión: se tienen en cuenta los valores de entrada, de salida y las excepciones declaradas.

Por ejemplo:

Comparator c = (a, b) -> Integer.compare(a.length(), b.length());

El método "compare" de Comparator tiene dos parámetros de entrada , y retorna un int. Esto es consistente con el lambda de la derecha, por lo cual es una asignación válida.

Runnable r = () -> { System.out.println("Running!"); }


El método "run" de la interfaz Runnable no recibe parámetros de entrada, y retorna void. Esto es consistente con el lambda de la derecha, y resulta en una asginación válida.

También se tienen en cuenta las excepciones chequeadas declaradas en la firma del método. El lambda sólo puede lanzar excepciones chequeadas si están declaradas en la interfaz.

Ejemplos de uso de lambdas en Java 8

Actualmente, para agregarle un listener a un botón podemos hacer:

btn.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent event) {
        System.out.println("Hola, mundo!");
    }
});     
Con expresiones lambda de Java 8 podemos hacer exactametne lo mismo con la siguiente expresión:

btn.setOnAction(
    event -> System.out.println("Hola, mundo!")
); 
También se puede usar el operador :: para hacer referencia a métodos estáticos de una clase:

public class Utils {
    public static int compareByLength(String in, String out){
        return in.length() - out.length();
    }
}

public class MyClass {
    public void doSomething() {
        String[] args = new String[] {"microsoft","apple","linux","oracle"}
        Arrays.sort(args, Utils::compareByLength);
    }
}  
... o también podemos acceder a métodos no estáticos:



public class MyClass implements Comparable<MyObject> {

    @Override
    public int compareTo(MyObject obj) {return ...}

    public void doSomething() {
        MyObject myObject = new MyObject();
        Arrays.sort(args, myObject::compareTo);
    }
}

No hay comentarios:

Publicar un comentario