TutorJava Nivel Básico: tutorial completo Java 21

La programación funcional en Java, introducida con Java 8, transforma la forma de procesar colecciones y datos. Las lambdas y el Streams API reducen el código boilerplate y expresan la intención de forma más clara.

Lambdas

Una lambda es una función anónima. Su sintaxis es (parámetros) -> expresión o (parámetros) -> { bloque; }:

// Lambda simple
Runnable saludo = () -> System.out.println("Hola desde lambda");
saludo.run();

// Lambda con parámetros
Comparator porLongitud = (a, b) -> Integer.compare(a.length(), b.length());

List palabras = new ArrayList<>(List.of("Java", "es", "genial", "y", "moderno"));
palabras.sort(porLongitud);
System.out.println(palabras); // [es, y, Java, genial, moderno]

Interfaces funcionales del JDK

El paquete java.util.function proporciona las interfaces funcionales más comunes:

Interfaz

Método

Uso

Supplier<T>

T get()

Produce un valor sin entrada

Consumer<T>

void accept(T)

Consume un valor, no devuelve nada

Function<T,R>

R apply(T)

Transforma T en R

Predicate<T>

boolean test(T)

Evalúa una condición

BiFunction<T,U,R>

R apply(T,U)

Combina dos valores en uno

Streams API

Los Streams proporcionan una forma de procesar colecciones de datos de forma declarativa, encadenando operaciones sin modificar la colección original:

List nombres = List.of("Ana", "Carlos", "Beatriz", "Pedro", "Alicia", "Luis");

// Contar nombres que empiezan por vocal
long conVocal = nombres.stream()
    .filter(n -> "AEIOUaeiou".indexOf(n.charAt(0)) >= 0)
    .count();
System.out.println("Con vocal inicial: " + conVocal);  // 2

// Obtener nombres de más de 4 letras, en mayúsculas, ordenados
List resultado = nombres.stream()
    .filter(n -> n.length() > 4)
    .map(String::toUpperCase)
    .sorted()
    .toList();
System.out.println(resultado);  // [ALICIA, BEATRIZ, CARLOS]

Operaciones intermedias y terminales

Las operaciones intermedias devuelven un Stream (lazy, se evalúan solo cuando llega la terminal). Las terminales producen un resultado y consumen el Stream:

List numeros = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// Suma de los cuadrados de los números pares
int suma = numeros.stream()
    .filter(n -> n % 2 == 0)   // intermedia: filtra pares
    .mapToInt(n -> n * n)       // intermedia: eleva al cuadrado
    .sum();                     // terminal: reduce a un int
System.out.println(suma);  // 220

// Agrupar por longitud
Map> porLongitud = nombres.stream()
    .collect(Collectors.groupingBy(String::length));

// Optional: manejo seguro de valores nulos
Optional primero = nombres.stream()
    .filter(n -> n.startsWith("Z"))
    .findFirst();
String valor = primero.orElse("No encontrado");
System.out.println(valor); // No encontrado

Streams paralelos

Para procesar grandes colecciones aprovechando múltiples núcleos, basta con cambiar stream() por parallelStream(). El orden de procesamiento no está garantizado:

long cuadradosSuma = LongStream.rangeClosed(1, 1_000_000)
    .parallel()
    .map(n -> n * n)
    .sum();
System.out.println(cuadradosSuma);

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP