¿Cómo se utiliza una lambda Predicate en Java?

¿Sabes cómo se utiliza una lambda Predicate en Java? Esta lambda es la única que aparece en los objetivos del examen de certificación OCAJ8P de Oracle, de manera que tienes que tener muy claro su funcionamiento.

More...

¿Qué es una lambda en Java?

Si ya hemos visto en otros artículos objetos y variables primitivas, hoy te voy a dar una introducción sobre las lambdas; en concreto, sobre la lambda Predicate en Java.

Una lambda es una referencia a una expresión

Recordarás que te he explicado en artículos anteriores que las variables primitivas son "cajitas" que contienen un valor. Esto significa que dichas cajitas tienen un tamaño concreto. Por ejemplo, una variable primitiva de tipo int solo puede contener un número entero con un valor de hasta 2.000.000.000.

Lambda Predicate en Java

¡No metas en una caja más de lo que puede contener!

Por otro lado, los objetos utilizan referencias. Una referencia no es como una variable, que contiene un objeto (como podría decirse de los primitivos), sino que es una especie de etiqueta que apunta al objeto. Así, puedes tener referencias con valor null (es decir, que no apuntan a ninguna parte).

En el caso de las lambdas, se utiliza una referencia a una expresión. Esto quiere decir que cuando utilizas una referencia a una lambda no estás pasando un valor concreto, o un objeto concreto, sino un método.

Es como si en lugar de pasar una cajita con un contenido concreto, o un objeto determinado, estás pasando una calculadora, que se puede utilizar para obtener un resultado de manera dinámica.

Una lambda en #Java es una herramienta para efectuar una operación, con menos código y de manera más transparente. #JavAutodidacta

Compártelo

Características básicas de una lambda en Java

Hay varias características básicas de una lambda en Java.

  • En primer lugar, ten en cuenta que, aunque solo la lambda de tipo Predicate entra en el examen de certificación OCA, no es la única lambda que nos facilita Java. Todas las demás tendrás que aprenderlas cuando te enfrentes al siguiente nivel de certificación, el OCP.
  • No olvides que, para utilizar las lambdas que facilita Java, tienes que importar el paquete java.util.function.*.
  • Por último (y esto ya no entra en el examen OCA), tú mismo puedes crear tus propias lambdas. Una lambda es, simplemente, una interfaz con un único método abstracto. Esta interfaz puede contener otros métodos (propios o heredados), pero solo uno puede ser abstracto. A este tipo de interfaz se la llama interfaz funcional, y al uso de lambdas se le llama programación funcional.

¿Qué es una lambda Predicate en Java?

Pasemos a la parte práctica del artículo.

Una lambda Predicate en Java sirve para comprobar si una condición dada es verdadera o falsa.

Por ejemplo, en lugar de pasar un objeto de tipo Boolean con valor true or false, o una variable primitiva de tipo boolean con dichos valores, pasas una referencia de tipo Predicate para determinar de manera dinámica si una condición dada es verdadera, o falsa. Esta es la calculadora a la que me refería más arriba: una lambda es una herramienta que utilizas en el código.

Esta operación se puede realizar sin una lambda, pero con lambdas el código es más breve y más transparente (sobre todo en clases anónimas, pero esas las verás en el examen de certificación OCP y en los listeners en Android. Al final del artículo te pongo un ejemplo de este último).

Esta es la estructura de la lambda Predicate en Java:

Uso de genéricos en las lambdas

Esa <T> que aparece en la signatura de la interface es lo que se llama un genérico. No necesitas aprender, por ahora, qué es un genérico (aunque sí para el OCP). Baste decir que en lugar de esa T tú utilizarás un tipo concreto. Por ejemplo, si utilizas el método test para comprobar una String, el tipo de tu lambda será Predicate<String> (similar a como utilizas una List<String>), y el método test aceptará únicamente objetos de tipo String.

¿Cómo utilizar una interfaz funcional?

A diferencia de las interfaces habituales, una clase no implementa una interfaz funcional. Cuando creas una referencia a una lambda Predicate en Java, lo que haces es implementar el método test en una línea, a la que le asignas una referencia. A continuación, puedes pasar esta referencia de un lado a otro, como cualquier otra referencia o variable. Esta lambda es un método portátil, por así decirlo.

Parece que la referencia es en sí un objeto, ¿no? Parece un objeto de tipo Predicate<String>, que ejecuta el método test. No obstante, no es un objeto: las interfaces no se pueden instanciar.

En realidad, lo que has hecho es algo similar a esto:

Como ves, el código con una lambda es bastante más breve y claro.

Diferencias entre aplicar programación funcional y no aplicarla

A continuación te enumero los pasos que tienes que seguir cuando implementas una lambda Predicate en Java, y los pasos que tienes que seguir para obtener el mismo resultado, sin lambda.

Código con lambda Predicate en Java

Código sin lambda

Importa el paquete java.util.function.

Importa el paquete java.util.function.

Crea una lambda de tipo Predicate<T>.

La clase implementa la interfaz Predicate<T>.

Ejecuta el método test con la referencia recién creada.

Implementa el método abstracto test en la clase.

Instancia un objeto de la clase creada.

Ejecuta el método test con la referencia recién creada.

Sintaxis de una lambda Predicate en Java

Como has observado, la manera en la que se implementa un método heredado de una interfaz y el modo en el que se instancia una lambda son bastante diferentes.

Tipo de la lambda

En primer lugar, debes darle un tipo concreto a la lambda. Es decir, cambia esa T por el tipo de argumento que vaya a aceptar el método test. Puede ser un objeto de cualquier tipo. Si creas un lambda sin tipo (Predicate, sin más), el método test aceptará objetos de tipo Object. Prueba el siguiente ejemplo:

La clase Object no contiene el método startsWith(), así que el código no compila.

Estructura de la lambda

A continuación, verás que la lambda en sí contiene tres partes:

  • Los argumentos del método de la lambda. En el caso de Predicate<T>, es uno. Este argumento ha de ser de un tipo concreto: si instancias una lambda Predicate<String>, el método test aceptará una String; si instancias una lambda Predicate<Integer>, el método test aceptará un Integer (recuerda que solo puedes utilizar objetos, no primitivos).

Los argumentos pueden aparecer entre paréntesis en cualquier caso, pero sin paréntesis si solo hay un argumento y no aparece su tipo:

Si los argumentos son más de uno (o ninguno), o si los argumentos van acompañados de su tipo, siempre irán entre paréntesis. En estos casos, eso sí, no serán lambdas Predicate.

No es obligatorio aclarar de qué tipo son los argumentos, ya que lo estás definiendo al crear la lambda: el parámetro del método test de Predicate<String> solo puede ser un String.

  • La flecha es un guión y un paréntesis angular, sin espacio entre ellos: ->
  • check
    Por último, a la derecha de la flecha aparece la implementación del método de la interfaz.

Échale un vistazo arriba, al ejemplo en el que utilizo la interfaz Predicate sin lambda. Como verás, en la lambda utilizas la implementación del método, pero sin la palabra clave return.

Si la implementación ocupa una sola línea, puede escribirla a continuación de la flecha, y terminarla con un punto y coma.

Sin embargo, si la implementación es más larga, tendrás que utilizar el cuerpo del método, incluidas llaves, palabra clave return y punto y coma dentro (y fuera) de las llaves. A continuación verás dos lambdas Predicate iguales, una en su versión resumida y la otra, en su versión extensa:

La versión extensa (con llaves, palabra clave return y punto y coma dentro de las llaves) se puede utilizar en cualquier caso, pero no es obligatoria si la implementación ocupa solo una línea. Además, no puedes utilizar una versión semiextensa: no puedes utilizar las llaves sin la palabra clave return, o utilizar return sin utilizar las llaves. En el siguiente ejemplo, ninguna de las lambdas compila:

Cómo utilizar lambdas en Android

Se pueden utilizar lambdas en Android si especificas en el AndroidManifest.xml la versión de Java que vas a utilizar. Las lambdas aparecieron en Java 8, así que asegúrate de añadir las siguientes líneas en tu código:

Y a continuación verás el resultado. Primero, el código sin lambda:

Y el mismo código, con una lambda:

Ejercicios recomendados

Si te estás preparando el OCA, ejercita bien la lambda Predicate, tanto en su forma abreviada como en la extensa. Si te estás preparando el OCP, crea tus propias lambdas y ejercita también las lambdas incluidas en el paquete java.util.function.

En Android, ¡convierte todos tus listeners en lambdas!