Ir al contenido principal

Expresiones Lambda

Empecemos con definir qué es una expresión lambda: son una forma de crear funciones anónimas y compactas en programación.

  • Son anónimas, no requieren un nombre explícito como las funciones tradicionales. 
  • Se utilizan cuando necesitas una función rápida y sencilla. 
  • No se reutilizan.
  • Ahorran espacio en el código.
  • Simplifican el uso de funciones en contextos donde solo se necesitan una vez, como al ordenar, mapear o filtrar listas.

La sintaxis de una expresión lambda en Python es la siguiente:

# Sintaxis de expresión lambda en Python
lambda argumentos: expresión

Podemos crear una expresión lambda que sume dos números.

suma = lambda x, y: x + y

La usamos de la siguiente forma:

resultado = suma(9, 4)  # resultado será 13

Algunos usos de expresiones lambda

Ordenar listas usando claves personalizadas.

personas = [
    {"nombre": "Ana", "edad": 23},
    {"nombre": "Luis", "edad": 19},
    {"nombre": "Juan", "edad": 30}
]

# Ordenar por edad
personas_ordenadas = sorted(personas, key=lambda persona: persona["edad"])

# Resultado: [{'nombre': 'Luis', 'edad': 19}, {'nombre': 'Ana', 'edad': 23}, {'nombre': 'Juan', 'edad': 30}]

Aplicar una función a cada elemento de una lista con map.

numeros = [1, 2, 3, 4, 5]

# Elevar cada número al cuadrado
cuadrados = list(map(lambda x: x ** 2, numeros))

# Resultado: [1, 4, 9, 16, 25]

Filtrar elementos de una lista con filter.

numeros = [1, 2, 3, 4, 5, 6, 7, 8]

# Filtrar números pares
pares = list(filter(lambda x: x % 2 == 0, numeros))

# Resultado: [2, 4, 6, 8]

Funciones en callbacks.

import tkinter as tk

ventana = tk.Tk()
boton = tk.Button(ventana, text="Haz clic", command=lambda: print("¡Botón presionado!"))
boton.pack()
ventana.mainloop()

Reducir expresiones en cálculos con reduce.

from functools import reduce

numeros = [1, 2, 3, 4]

# Calcular el producto de todos los números en la lista
producto = reduce(lambda x, y: x * y, numeros)

# Resultado: 24 (1 * 2 * 3 * 4)

Expresiones Lambda en Java

Se tratan de funciones que no necesitan pertenecer a alguna clase previamente definida.

Permiten crear funciones anónimas de una manera parecida a Python, pero en Java, las lambdas solo se pueden usar en interfaces funcionales, es decir, interfaces con un único método abstracto (como Runnable, Comparator, etc.).

Sintaxis básica:

(parámetros) -> { cuerpo-lambda}

Donde:

  1. Parámetros: La lista de parámetros que acepta la función. Si hay un solo parámetro, puedes omitir los paréntesis. 
  2. Operador ->: Separa los parámetros del cuerpo de la función. 
  3. Cuerpo: Contiene el código que se ejecutará cuando se llame a la función lambda. Si el cuerpo es una única expresión, puedes omitir las llaves {} y el valor se devolverá automáticamente.

Las expresiones lambda en Java son especialmente útiles para:

  • Implementar métodos de interfaces funcionales rápidamente. 
  • Simplificar código en comparadores (Comparator). 
  • Usar en hilos (Runnable). 
  • Procesar colecciones usando Streams.

Ejemplos en Java

Expresión Lambda Simple (Sumar dos números)

@FunctionalInterface
interface Operacion {
    int calcular(int a, int b);
}

Implementación:

Operacion suma = (a, b) -> a + b;

int resultado = suma.calcular(5, 3); // resultado será 8

Usar Expresiones Lambda con Comparator.

List<String> nombres = Arrays.asList("Ana", "Luis", "Pedro");

nombres.sort((a, b) -> a.compareTo(b));

// Resultado: [Ana, Luis, Pedro]

Expresión Lambda con Runnable.

Runnable tarea = () -> System.out.println("¡Tarea en un hilo!");

new Thread(tarea).start();

Filtrar y Procesar Datos en Colecciones (Streams).

List<Integer> numeros = Arrays.asList(1, 2, 3, 4, 5, 6);

numeros.stream()
       .filter(n -> n % 2 == 0) // Filtrar números pares
       .forEach(n -> System.out.println(n)); // Imprimir pares

// Resultado: 2 4 6


Un ejemplo completo:

import java.util.*;

class Persona {
    String nombre;
    int edad;

    Persona(String nombre, int edad) {
        this.nombre = nombre;
        this.edad = edad;
    }

    public String toString() {
        return nombre + " (" + edad + ")";
    }
}

public class EjemploLambda {
    public static void main(String[] args) {
        List<Persona> personas = Arrays.asList(
            new Persona("Ana", 23),
            new Persona("Luis", 19),
            new Persona("Juan", 30)
        );

        // Ordenar personas por edad usando una expresión lambda
        personas.sort((p1, p2) -> Integer.compare(p1.edad, p2.edad));

        // Imprimir personas ordenadas
        personas.forEach(p -> System.out.println(p));
    }
}


Existen cuatro principales tipos de expresiones lambda:

  1. Consumidores (Consumer).
  2. Proveedores (Supplier).
  3. Funciones(Function) (Unarios & Binarios). 
  4. Predicados(Predicate).

Se importan de la siguiente forma:

import java.util.function.Consumer;//interface
import java.util.function.Function;//interface
import java.util.function.Supplier;//interface
import java.util.function.Predicate;//interface
¿Para qué me sirve cada una de éstas interfaces?

Consumer: Puede o no recibir algún valor y no devolver nada.

import java.function.Consumer;
 
import static java.lang.System.out;
 
//...
 
Consumer consumer = (cad) -> out.println("Hola, "+cad);
 
consumer.accept(new String("Alquimista"));

Function: Puede tomar dos valores de distinto tipo y devolver un valor en específico.

//...
import java.function.Function;
 
import static java.lang.System.out;
 
//...
 
Function<Integer, String> function = num -> {
    if(num%3==0  && num%5==0){
      return num+" divisible entre 3 y 5";
    }else{
      return num+" no es divisible entre 3 y 5";
    }
};
 
out.println(function.apply(new Integer("25")));
out.println(function.apply(new Integer("8")));

Predicate: Puede tomar valores y devolver un valor booleano.

//...
import java.util.function.Predicate;
import static java.lang.System.out;
//...
Predicate predicate = (cad) -> String.valueOf(cad).endsWith(".xml");
out.println(predicate.test("doc.pdf")? "Cierto" : "Falso");
out.println(predicate.test("doc.xml")? "Cierto" : "Falso");

Supplier: No recibe valores, pero devuelve un valor.

//...
import java.util.function.Supplier;
import java.util.Random;
import static java.lang.System.out;
//...
Random random = new Random();
String[] moneda = {"AGUILA","SOL"};
Supplier supplier = () -> moneda[random.nextInt(2)];
out.println("Moneda: "+supplier.get());

Hemos visto que son las expresiones lambda tanto en Python como en Java. Continuaremos con este tema.

Enlaces:

https://codemonkeyjunior.wordpress.com/2018/04/23/un-vistazo-a-lambdas-java-8/
https://codemonkeyjunior.wordpress.com/2019/03/19/java-8-java-util-function/

Comentarios