¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
  1. Libros
  2. Java
  3. Las expresiones lambda
Extrait - Java Los fundamentos del lenguaje (con ejercicios corregidos)
Extractos del libro
Java Los fundamentos del lenguaje (con ejercicios corregidos) Volver a la página de compra del libro

Las expresiones lambda

Introducción

En el ecosistema de Java, las expresiones lambda han sido largamente esperadas desde hace mucho tiempo. Aparecieron con Java 8. Java se ha puesto al día con ciertos lenguajes competitivos, como C #. Pero ¿qué son las expresiones lambda? Son simplemente funciones que se pueden pasar como un parámetro de otra función. Esto simplifica el código en ciertas situaciones donde el desarrollo de objetos ofrece soluciones detalladas basadas en clases anónimas en particular.

Funcionamiento

1. Las interfaces funcionales

El funcionamiento de las expresiones lambda se basa en el funcionamiento de las interfaces. De hecho, un parámetro de método que espera una expresión lambda es simplemente un parámetro del tipo de una interfaz. Sin embargo, esta interfaz debe respetar una regla importante: debe definir la firma de un solo método abstracto.

En este caso, la interfaz se convierte en una interfaz funcional. Siempre es posible tener métodos adicionales si no son abstractos (métodos predeterminados, métodos estáticos).

Por ejemplo, he aquí el código simplificado para la interfaz java.util.Comparator<T>. Su función es proporcionar un mecanismo para comparar objetos del mismo tipo:

@FunctionalInterface  
public interface Comparator<T> {   
   int compare(T o1, T o2);   
  ...  
} 

Una interfaz funcional es una interfaz como las demás en su estructura. La diferencia es la presencia de la anotación @FunctionalInterface, que también es opcional, pero que permite al compilador realizar las comprobaciones de coherencia necesarias. Siempre que no tenga exactamente un único método abstracto en la interfaz, el compilador le indicará el siguiente mensaje:

images/cap4_1.png

Java ofrece un conjunto de interfaces funcionales que responden a la gran mayoría de las situaciones. Por lo tanto, lo más probable es que no necesite crearlas usted mismo, o al menos no con frecuencia. Están disponibles en el paquete java.util.function. Una sección dedicada le permitirá explorar el contenido de este paquete. 

Un ejemplo concreto del uso de interfaces funcionales es el método de clasificación de la interfaz List <T>. Este método permite ordenar los elementos de la lista de acuerdo con un criterio de comparación proporcionado como un parámetro del método, en la forma de una implementación de la interfaz Comparator <T> que, le recuerdo, permite comparar dos objetos del mismo tipo.

Aquí está la firma del método sort:

void java.util.List.sort (Comparador <? super String> c) 

El método sort recibe como argumento de tipo Comparator <T>. Como es una interfaz funcional, es posible pasar como parámetro:

  • Una instancia de clase que implementa...

Manipulación de las colecciones

1. La API Stream

La aparición de expresiones lambda ha permitido la creación o el enriquecimiento de un cierto número de API. La más característica es la API Stream, que permite la manipulación de flujos de elementos. Esta API simplifica el manejo de colecciones. El desarrollador se concentra en las operaciones que se llevarán a cabo, sin preocuparse por cómo recorrer la colección.

Esta sección tiene como objetivo presentar el funcionamiento de esta API, para ser autónomo al final de este capítulo.

2. Teoría

En general, las colecciones se utilizan con objeto de almacenar información para que se pueda recuperar o realizar operaciones con ella. La técnica clásica para realizar operaciones en los elementos contenidos en una colección consiste en hacer un bucle for o usar el iterador asociado con la colección. Esta solución puede ser reemplazada ventajosamente por el uso de streams y pipelines. Para ilustrar el funcionamiento de estos dos elementos, podemos hacer el paralelismo con el funcionamiento de una fábrica.

Nuestra fábrica recibe la materia prima, que pasa a través de diferentes unidades de procesamiento, para obtener el producto terminado como salida. En nuestro caso, los datos presentes en la colección representan la materia prima. Estos se transportan a través de objetos que generalmente implementan la interfaz Stream. Las unidades de procesamiento están representadas por los pipelines. Estos pueden producir un resultado directamente explotable (el producto terminado) u otro objeto Stream, que alimentará un nuevo pipeline. 

Todas las clases que implementan la interfaz Collection son capaces de proporcionar un objeto de tipo Stream. Este objeto es el responsable de la iteración sobre los elementos presentes en la colección.

Los pipelines son un poco más complejos, ya que están formados por varios elementos.

El primero representa la fuente de la cual el pipeline obtendrá la información sobre la que llevará a cabo el procesamiento o los procesamientos. Por supuesto, es un objeto Stream que será la fuente de un pipeline. Las operaciones están representadas por los diferentes métodos definidos en la interfaz Stream. Estos métodos...

Conclusión

Este capítulo le ha presentado el poder de las expresiones lambda y el valor de algunas API que giran en torno a ellas. Por supuesto, esto es solo una breve descripción. Puede descubrir la riqueza de estas API a medida que las necesite.