Java Streams
Guía visual completa · stream() · mapToDouble · map · flatMap · filter · collect
■ ¿Qué es un Stream?
Un Stream tiene 3 partes que forman un pipeline:
■ FUENTE → ■ OPERACIONES INTERMEDIAS
→ ■ TERMINAL
■ Intermedias: transforman el stream y devuelven otro stream — se encadenan
■ Terminales: cierran el stream y producen el resultado final
■ 1 · .stream()
Convierte la List<Asignatura> en un flujo de elementos uno a uno:
Asignatura1 Asignatura2 Asignatura3
↓ .stream()
■ flujo de Asignaturas una a una
■ 2 · .mapToDouble(Asignatura::getCreditos)
Transforma cada Asignatura en un double aplicando getCreditos():
Asignatura("Cálculo", 6.0)
→ 6.0
Asignatura("Física", 6.0)
→ 6.0
Asignatura("Historia",6.0)
→ 6.0
Asignatura::getCreditos es una referencia a método, equivale a:
// ■ Esto:
.mapToDouble(Asignatura::getCreditos)
// ■ Es lo mismo que esto:
.mapToDouble(a -> [Link]())
■ 1 · FORMAS DE CREAR UN STREAM
// ■ Desde una lista
List<String> lista = [Link]("a", "b", "c");
[Link]();
// ■ Desde un array
String[] array = {"a", "b", "c"};
[Link](array);
// ■ Desde valores directos
[Link]("a", "b", "c");
// ■ Stream infinito con límite
[Link](0, n -> n + 1).limit(10); // 0,1,2,3...9
// ■ Stream vacío
[Link]();
■ 2 · OPERACIONES INTERMEDIAS
■ map — transforma cada elemento
// ■ Objeto → otro tipo
List<String> nombres = [Link]("ana", "bob", "eva");
[Link]()
.map(String::toUpperCase) // cada String → mayúsculas
.collect([Link]());
// → ["ANA", "BOB", "EVA"]
// ■ Objeto → otro objeto
[Link]()
.map(a -> [Link]()) // Asignatura → String
.collect([Link]());
// → ["Cálculo", "Física", "Historia"]
■ mapToInt / mapToDouble / mapToLong — transforma a primitivo
// Devuelven IntStream / DoubleStream / LongStream
// con operaciones: sum(), average(), max(), min()
[Link]()
.mapToInt(Asignatura::getCreditos)
.sum(); // → 18
[Link]()
.mapToDouble(Asignatura::getCreditos)
.average()
.getAsDouble(); // → 6.0
[Link]()
.mapToInt(Asignatura::getCreditos)
.max()
.getAsInt(); // → 6
■ flatMap — aplana listas dentro de listas
// ■ Problema: tienes una lista de listas
List<List<String>> cursos = [Link](
[Link]("Cálculo", "Física"),
[Link]("Historia", "Arte"),
[Link]("Java", "Python")
);
// ■ Sin flatMap → Stream<List<String>> no puedes operar bien
// ■ Con flatMap → Stream<String> todos los elementos juntos
[Link]()
.flatMap(lista -> [Link]()) // "aplana"
.collect([Link]());
// → ["Cálculo", "Física", "Historia", "Arte", "Java", "Python"]
// ■ Ejemplo real: todas las optativas de todos los grados
[Link]()
.flatMap(g -> [Link]().stream())
.collect([Link]());
■ filter — filtra por condición
// ■ Solo asignaturas con más de 4 créditos
[Link]()
.filter(a -> [Link]() > 4)
.collect([Link]());
// ■ Solo nombres que empiezan por "A"
[Link]()
.filter(n -> [Link]("A"))
.collect([Link]());
■ sorted — ordena
// ■ Orden natural
[Link]().sorted().collect([Link]());
// → ["ana", "bob", "eva"]
// ■ Orden por nombre
[Link]()
.sorted([Link](Asignatura::getNombre))
.collect([Link]());
// ■ Orden inverso
[Link]()
.sorted([Link](Asignatura::getCreditos).reversed())
.collect([Link]());
■ distinct — elimina duplicados
List<Integer> nums = [Link](1, 2, 2, 3, 3, 3);
[Link]()
.distinct()
.collect([Link]());
// → [1, 2, 3]
■ 3 · OPERACIONES TERMINALES
■ collect — recoge en una colección
// ■ A List
.collect([Link]());
// ■ A Set (sin duplicados)
.collect([Link]());
// ■ A String uniendo con separador
[Link]()
.collect([Link](", "));
// → "ana, bob, eva"
// ■ A Map
[Link]()
.collect([Link](
Asignatura::getNombre, // clave
Asignatura::getCreditos // valor
));
// ■ Agrupando — como GROUP BY en SQL
[Link]()
.collect([Link](Asignatura::getCreditos));
// → {6=[Cálculo, Física, Historia], 4=[Optativa corta]}
■ anyMatch / allMatch / noneMatch
// ■ ¿Alguna tiene más de 8 créditos?
boolean alguna = [Link]()
.anyMatch(a -> [Link]() > 8); // false
// ■ ¿Todas tienen al menos 6 créditos?
boolean todas = [Link]()
.allMatch(a -> [Link]() >= 6); // true
// ■ ¿Ninguna tiene 0 créditos?
boolean ninguna = [Link]()
.noneMatch(a -> [Link]() == 0); // true
■ reduce — combina todos en uno
// ■ Suma manual (equivale a sum())
int total = [Link](1,2,3,4).stream()
.reduce(0, (acum, n) -> acum + n);
// → 10
// ■ Concatenar strings
String res = [Link]()
.reduce("", (acum, n) -> acum + n + " ");
// → "ana bob eva "
■ TABLA RESUMEN
Método Qué hace Tipo
.stream() Abre el pipeline desde una colección inicio
.map() Transforma cada elemento a otro tipo intermedia
.mapToInt/Double() Transforma a primitivo numérico intermedia
.flatMap() Aplana lista de listas en una sola intermedia
.filter() Filtra elementos por condición intermedia
.sorted() Ordena el stream intermedia
.distinct() Elimina duplicados intermedia
.limit() / .skip() Recorta el stream intermedia
.collect() Recoge en List, Set, Map, String... terminal
.sum() / .average() Operaciones numéricas (solo *ToInt/Double) terminal
.count() Cuenta los elementos terminal
.anyMatch()/allMatch() Comprobaciones booleanas terminal
.findFirst() Devuelve el primer elemento (Optional) terminal
.reduce() Combina todos los elementos en uno terminal
.forEach() Ejecuta una acción por cada elemento terminal
■ EJEMPLO COMBINANDO TODO
Nombres en mayúsculas de optativas con más de 4 créditos, ordenadas y separadas por coma:
String resultado = [Link]().stream()
.filter(a -> [Link]() > 4) // ■ filtra
.sorted([Link](Asignatura::getNombre)) // ■ ordena
.map(Asignatura::getNombre) // ■ extrae nombre
.map(String::toUpperCase) // ■ mayúsculas
.collect([Link](", ")); // ■ une
// → "CÁLCULO, FÍSICA, HISTORIA"