Inicio > Cursos > Java > Streams y Lambdas (Java 8+)
JavaJava ModernoLección 12 de 15

Streams y Lambdas (Java 8+)

Java 8 (2014) fue la mayor actualización del lenguaje en décadas. Introdujo lambdas: funciones anónimas que se pueden pasar como argumentos. Antes de Java 8, para filtrar una lista necesitabas un loop for con un if y agregar a otra lista manualmente. Con lambdas y Streams, el mismo código es una sola línea: lista.stream().filter(x -> x > 0).collect(toList()). Es la adopción de programación funcional en un lenguaje históricamente orientado a objetos.

Las Streams son secuencias de elementos que soportan operaciones en cadena. Las operaciones intermedias (filter, map, sorted, distinct) son lazy: no se ejecutan hasta que llega una operación terminal (collect, count, sum, findFirst). Esto es eficiente: si filtras 1 millón de elementos y solo necesitas el primero con findFirst(), Java puede parar en cuanto lo encuentre sin procesar el resto. El método map transforma cada elemento, reduce los combina en un resultado único.

import java.util.*;
import java.util.stream.*;

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

// Stream operations
List<Integer> pares = numeros.stream()
    .filter(n -> n % 2 == 0)      // Lambda: filtrar pares
    .collect(Collectors.toList()); // Terminal: colectar

List<Integer> dobles = numeros.stream()
    .map(n -> n * 2)
    .collect(Collectors.toList());

int suma = numeros.stream()
    .reduce(0, (acc, n) -> acc + n); // 55

// O más conciso:
int suma2 = numeros.stream()
    .mapToInt(Integer::intValue)
    .sum();

// Streams con objetos
record Persona(String nombre, int edad, String ciudad) {}

List<Persona> personas = List.of(
    new Persona("Ana", 25, "Madrid"),
    new Persona("Carlos", 17, "Lima"),
    new Persona("María", 30, "Bogotá")
);

List<String> nombresAdultos = personas.stream()
    .filter(p -> p.edad() >= 18)
    .sorted(Comparator.comparing(Persona::nombre))
    .map(Persona::nombre)
    .collect(Collectors.toList());
// [Ana, María]

// Agrupación
Map<String, List<Persona>> porCiudad = personas.stream()
    .collect(Collectors.groupingBy(Persona::ciudad));

// Optional - evita NullPointerException
Optional<Persona> primera = personas.stream()
    .filter(p -> p.edad() > 20)
    .findFirst();
primera.ifPresent(p -> System.out.println(p.nombre()));
Consejo⚡ Las Streams son lazy (perezosas): las operaciones intermedias (filter, map) no se ejecutan hasta que llega una operación terminal (collect, sum, findFirst).
← Sealed Classes y Pattern MatchingExcepciones y Manejo de Errores →

Practica esta lección

Resuelve los ejercicios del curso de Java en la app, gratis y con corrección automática.

Empezar a practicar