Java
Tutorial Java: Operaciones finales con Streams: collect()
Aprende a usar collect() en Java Streams para transformar datos en listas, conjuntos y mapas con ejemplos prácticos y explicaciones claras.
Aprende Java y certifícatecollect(), toList(), toSet(), toMap()
La operación terminal collect() es una de las herramientas más versátiles en el API Stream de Java, permitiendo transformar los elementos de un stream en diferentes tipos de colecciones o valores. Esta operación funciona en conjunto con la interfaz Collector, que define cómo se acumularán los elementos procesados.
La sintaxis básica de collect() es:
<R, A> R collect(Collector<? super T, A, R> collector)
Donde:
- T es el tipo de elementos en el stream
- R es el tipo del resultado
- A es el tipo del acumulador intermedio
La clase Collectors proporciona implementaciones predefinidas que facilitan las operaciones más comunes. Veamos los colectores fundamentales:
Collector toList()
El método toList() convierte los elementos de un stream en una lista:
import java.util.List;
import java.util.stream.Collectors;
public class EjemploToList {
public static void main(String[] args) {
List<String> nombres = List.of("Ana", "Carlos", "Beatriz", "Daniel");
// Filtrar nombres que empiezan con 'A' o 'B' y convertirlos a lista
List<String> filtrados = nombres.stream()
.filter(n -> n.startsWith("A") || n.startsWith("B"))
.collect(Collectors.toList());
System.out.println("Nombres filtrados: " + filtrados);
}
}
Este código produce una lista con los elementos "Ana" y "Beatriz". A partir de Java 16, también podemos usar el método toList() directamente en el Stream:
List<String> filtrados = nombres.stream()
.filter(n -> n.startsWith("A") || n.startsWith("B"))
.toList(); // Método directo desde Java 16
La diferencia principal es que el método directo toList() devuelve una lista inmutable, mientras que Collectors.toList() devuelve una lista modificable.
Collector toSet()
El método toSet() convierte los elementos de un stream en un conjunto (Set), eliminando automáticamente los duplicados:
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class EjemploToSet {
public static void main(String[] args) {
List<String> palabras = List.of("Java", "Python", "Java", "JavaScript", "Python");
// Convertir a Set para eliminar duplicados
Set<String> lenguajesUnicos = palabras.stream()
.collect(Collectors.toSet());
System.out.println("Lenguajes únicos: " + lenguajesUnicos);
}
}
Este código produce un conjunto con los elementos "Java", "Python" y "JavaScript", eliminando los duplicados.
Collector toMap()
El método toMap() permite convertir los elementos de un stream en un mapa, especificando cómo extraer las claves y los valores:
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class Producto {
private String nombre;
private double precio;
public Producto(String nombre, double precio) {
this.nombre = nombre;
this.precio = precio;
}
public String getNombre() { return nombre; }
public double getPrecio() { return precio; }
}
public class EjemploToMap {
public static void main(String[] args) {
List<Producto> productos = List.of(
new Producto("Laptop", 1200.0),
new Producto("Teléfono", 800.0),
new Producto("Tablet", 500.0)
);
// Crear un mapa con nombre como clave y precio como valor
Map<String, Double> preciosPorProducto = productos.stream()
.collect(Collectors.toMap(
Producto::getNombre, // función para extraer la clave
Producto::getPrecio // función para extraer el valor
));
System.out.println("Precios por producto: " + preciosPorProducto);
}
}
Este código crea un mapa donde las claves son los nombres de los productos y los valores son sus precios.
Si existe la posibilidad de claves duplicadas, podemos proporcionar una función de resolución de conflictos:
Map<String, Double> preciosPorProducto = productos.stream()
.collect(Collectors.toMap(
Producto::getNombre,
Producto::getPrecio,
(precioExistente, precioNuevo) -> precioNuevo // En caso de duplicados, usar el nuevo valor
));
Otros colectores útiles
Además de los colectores básicos, Collectors ofrece métodos para realizar operaciones de agregación:
joining(): Concatena elementos de tipo String:
List<String> frutas = List.of("Manzana", "Banana", "Cereza");
String resultado = frutas.stream()
.collect(Collectors.joining(", "));
System.out.println("Frutas: " + resultado); // Imprime: Frutas: Manzana, Banana, Cereza
summingInt(), summingLong(), summingDouble(): Suman valores numéricos:
List<Producto> productos = List.of(
new Producto("Laptop", 1200.0),
new Producto("Teléfono", 800.0),
new Producto("Tablet", 500.0)
);
double precioTotal = productos.stream()
.collect(Collectors.summingDouble(Producto::getPrecio));
System.out.println("Precio total: " + precioTotal); // Imprime: Precio total: 2500.0
averagingInt(), averagingLong(), averagingDouble(): Calculan promedios:
double precioPromedio = productos.stream()
.collect(Collectors.averagingDouble(Producto::getPrecio));
System.out.println("Precio promedio: " + precioPromedio); // Imprime: Precio promedio: 833.3333...
counting(): Cuenta elementos:
long cantidad = productos.stream()
.collect(Collectors.counting());
System.out.println("Cantidad de productos: " + cantidad); // Imprime: Cantidad de productos: 3
maxBy(), minBy(): Encuentran el máximo o mínimo según un comparador:
import java.util.Comparator;
import java.util.Optional;
Optional<Producto> masBarato = productos.stream()
.collect(Collectors.minBy(Comparator.comparing(Producto::getPrecio)));
masBarato.ifPresent(p -> System.out.println("Producto más barato: " + p.getNombre()));
Colectores personalizados
También podemos crear colectores personalizados utilizando el método Collectors.collectingAndThen(), que permite aplicar una función final al resultado de otro colector:
List<Integer> numeros = List.of(1, 2, 3, 4, 5);
// Colectar a lista y convertir a array inmutable
Integer[] arrayNumeros = numeros.stream()
.collect(Collectors.collectingAndThen(
Collectors.toList(),
lista -> lista.toArray(new Integer[0])
));
La operación collect() junto con los colectores predefinidos proporciona una forma elegante y funcional de transformar streams en estructuras de datos útiles. Estos colectores simplifican operaciones que de otro modo requerirían código imperativo más extenso y propenso a errores.
Otros ejercicios de programación de Java
Evalúa tus conocimientos de esta lección Operaciones finales con Streams: collect() con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
Streams: match
Gestión de errores y excepciones
CRUD en Java de modelo Customer sobre un ArrayList
Clases abstractas
Listas
Métodos de la clase String
Streams: reduce()
API java.nio 2
Polimorfismo
Pattern Matching
Streams: flatMap()
Llamada y sobrecarga de funciones
Métodos referenciados
Métodos de la clase String
Representación de Fecha
Operadores lógicos
Inferencia de tipos con var
Tipos de datos
Estructuras de iteración
Streams: forEach()
Objetos
Funciones lambda
Uso de Scanner
Tipos de variables
Streams: collect()
Operadores aritméticos
Arrays y matrices
Clases y objetos
Interfaz funcional Consumer
CRUD en Java de modelo Customer sobre un HashMap
Interfaces
Enumeraciones Enums
API Optional
Interfaz funcional Function
Encapsulación
Interfaces
Uso de API Optional
Representación de Hora
Herencia básica
Clases y objetos
Interfaz funcional Supplier
HashMap
Sobrecarga de métodos
Polimorfismo de tiempo de ejecución
OOP en Java
Sobrecarga de métodos
CRUD de productos en Java
Clases sealed
Creación de Streams
Records
Encapsulación
Streams: min max
Herencia
Métodos avanzados de la clase String
Funciones
Polimorfismo de tiempo de compilación
Reto sintaxis Java
Conjuntos
Estructuras de control
Recursión
Excepciones
Herencia avanzada
Estructuras de selección
Uso de interfaces
Operadores
Variables
HashSet
Objeto Scanner
Streams: filter()
Operaciones de Streams
Interfaz funcional Predicate
Streams: sorted()
Configuración de entorno
Uso de variables
Clases
Streams: distinct()
Streams: count()
ArrayList
Mapas
Datos de referencia
Interfaces funcionales
Métodos básicos de la clase String
Tipos de datos
Clases abstractas
Instalación
Funciones
Excepciones
Estructuras de control
Herencia de clases
La clase Scanner
Generics
Streams: map()
Funciones y encapsulamiento
Todas las lecciones de Java
Accede a todas las lecciones de Java y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Instalación De Java
Introducción Y Entorno
Configuración De Entorno Java
Introducción Y Entorno
Tipos De Datos
Sintaxis
Variables
Sintaxis
Operadores
Sintaxis
Estructuras De Control
Sintaxis
Funciones
Sintaxis
Recursión
Sintaxis
Arrays Y Matrices
Sintaxis
Excepciones
Programación Orientada A Objetos
Clases Y Objetos
Programación Orientada A Objetos
Encapsulación
Programación Orientada A Objetos
Herencia
Programación Orientada A Objetos
Clases Abstractas
Programación Orientada A Objetos
Interfaces
Programación Orientada A Objetos
Sobrecarga De Métodos
Programación Orientada A Objetos
Polimorfismo
Programación Orientada A Objetos
La Clase Scanner
Programación Orientada A Objetos
Métodos De La Clase String
Programación Orientada A Objetos
Excepciones
Programación Orientada A Objetos
Records
Programación Orientada A Objetos
Pattern Matching
Programación Orientada A Objetos
Inferencia De Tipos Con Var
Programación Orientada A Objetos
Enumeraciones Enums
Programación Orientada A Objetos
Generics
Programación Orientada A Objetos
Clases Sealed
Programación Orientada A Objetos
Listas
Framework Collections
Conjuntos
Framework Collections
Mapas
Framework Collections
Funciones Lambda
Programación Funcional
Interfaz Funcional Consumer
Programación Funcional
Interfaz Funcional Predicate
Programación Funcional
Interfaz Funcional Supplier
Programación Funcional
Interfaz Funcional Function
Programación Funcional
Métodos Referenciados
Programación Funcional
Creación De Streams
Programación Funcional
Operaciones Intermedias Con Streams: Map()
Programación Funcional
Operaciones Intermedias Con Streams: Filter()
Programación Funcional
Operaciones Intermedias Con Streams: Distinct()
Programación Funcional
Operaciones Finales Con Streams: Collect()
Programación Funcional
Operaciones Finales Con Streams: Min Max
Programación Funcional
Operaciones Intermedias Con Streams: Flatmap()
Programación Funcional
Operaciones Intermedias Con Streams: Sorted()
Programación Funcional
Operaciones Finales Con Streams: Reduce()
Programación Funcional
Operaciones Finales Con Streams: Foreach()
Programación Funcional
Operaciones Finales Con Streams: Count()
Programación Funcional
Operaciones Finales Con Streams: Match
Programación Funcional
Api Optional
Programación Funcional
Transformación
Programación Funcional
Reducción Y Acumulación
Programación Funcional
Mapeo
Programación Funcional
Streams Paralelos
Programación Funcional
Agrupación Y Partición
Programación Funcional
Filtrado Y Búsqueda
Programación Funcional
Api Java.nio 2
Entrada Y Salida Io
Fundamentos De Io
Entrada Y Salida Io
Leer Y Escribir Archivos
Entrada Y Salida Io
Httpclient Moderno
Entrada Y Salida Io
Clases De Nio2
Entrada Y Salida Io
Api Java.time
Api Java.time
Localtime
Api Java.time
Localdatetime
Api Java.time
Localdate
Api Java.time
Executorservice
Concurrencia
Virtual Threads (Project Loom)
Concurrencia
Future Y Completablefuture
Concurrencia
Spring Framework
Frameworks Para Java
Micronaut
Frameworks Para Java
Maven
Frameworks Para Java
Gradle
Frameworks Para Java
Lombok Para Java
Frameworks Para Java
Quarkus
Frameworks Para Java
Ecosistema Jakarta Ee De Java
Frameworks Para Java
Introducción A Junit 5
Testing
Certificados de superación de Java
Supera todos los ejercicios de programación del curso de Java y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender la función y sintaxis de la operación terminal collect() en Streams.
- Utilizar colectores predefinidos como toList(), toSet() y toMap() para transformar streams en colecciones.
- Aplicar colectores para realizar operaciones de agregación como sumas, promedios y conteos.
- Crear y usar colectores personalizados con collectingAndThen() para transformar resultados.
- Diferenciar entre listas mutables e inmutables generadas por diferentes métodos de colectores.