A logo showing the text blog.marcnuri.com
English
Inicio»Desarrollo Backend»Java Streams: Convertir List en Map

Entradas Recientes

  • Resumen de 2025: El Año de la IA
  • Synology DS224+: Cómo actualizar discos duros en RAID 1
  • Fabric8 Kubernetes Client 7.5 está disponible!
  • Impulsando Mi Productividad como Desarrollador con IA en 2025
  • Black Box vs White Box Testing: Cuándo Usar Cada Enfoque

Categorías

  • Antiguo
  • Cloud Native
  • Desarrollo Backend
  • Desarrollo Frontend
  • Herramientas
  • Ingeniería de calidad
  • Inteligencia Artificial
  • JavaScript
  • Operaciones
  • Personal
  • Proyectos personales
  • Reflexiones sobre Ingeniería

Archivos

  • enero 2026
  • diciembre 2025
  • octubre 2025
  • septiembre 2025
  • julio 2025
  • mayo 2025
  • abril 2025
  • marzo 2025
  • febrero 2025
  • enero 2025
  • diciembre 2024
  • noviembre 2024
  • agosto 2024
  • junio 2024
  • mayo 2024
  • abril 2024
  • marzo 2024
  • febrero 2024
  • enero 2024
  • diciembre 2023
  • noviembre 2023
  • octubre 2023
  • septiembre 2023
  • agosto 2023
  • julio 2023
  • junio 2023
  • mayo 2023
  • abril 2023
  • marzo 2023
  • febrero 2023
  • enero 2023
  • diciembre 2022
  • noviembre 2022
  • octubre 2022
  • septiembre 2022
  • agosto 2022
  • julio 2022
  • junio 2022
  • mayo 2022
  • marzo 2022
  • febrero 2022
  • enero 2022
  • diciembre 2021
  • noviembre 2021
  • octubre 2021
  • septiembre 2021
  • agosto 2021
  • julio 2021
  • enero 2021
  • diciembre 2020
  • octubre 2020
  • septiembre 2020
  • agosto 2020
  • junio 2020
  • mayo 2020
  • marzo 2020
  • febrero 2020
  • enero 2020
  • noviembre 2019
  • septiembre 2019
  • julio 2019
  • diciembre 2018
  • agosto 2018
  • julio 2018
  • junio 2018
  • mayo 2018
  • marzo 2018
  • febrero 2018
  • noviembre 2017
  • octubre 2017
  • agosto 2017
  • julio 2017
  • enero 2017
  • julio 2016
  • enero 2016
  • diciembre 2015
  • noviembre 2015
  • diciembre 2014
  • noviembre 2014
  • octubre 2014
  • marzo 2014
  • febrero 2011
  • junio 2008
  • mayo 2008
  • abril 2008
  • enero 2008
  • junio 2007
  • mayo 2007
  • abril 2007
  • marzo 2007

Java Streams: Convertir List en Map

2018-03-28 en Desarrollo Backend etiquetado Collector / Java / List / Map / Streams por Marc Nuri | Última actualización: 2026-01-27
English version

Introducción

Convertir un List en un Map es una de las operaciones más comunes cuando trabajamos con Java Streams. Los mapas son estructuras de datos compuestas por pares clave-valor donde cada clave es única, lo que permite realizar búsquedas rápidas sin necesidad de recorrer toda la colección.

En este artículo, te muestro todo lo que necesitas saber para convertir un List a un Map usando Collectors.toMap():

  • Conversión básica cuando las claves son únicas
  • Manejo de claves duplicadas con funciones de fusión
  • Mantener el orden de inserción con LinkedHashMap
  • Ordenar claves con TreeMap
  • Crear mapas inmutables con toUnmodifiableMap()
  • Manejo de valores nulos y cómo evitar NullPointerException

Para los ejemplos, usaré un record Repository:

Repository.java
public record Repository(String name, String fullName, String description, boolean fork) {}

Consejo

Si usas una versión anterior a Java 16, puedes emplear una clase tradicional con getters.

Lista a Mapa sin duplicidades

Cuando estés seguro de que el List no contiene claves duplicadas, usa la versión básica de dos argumentos de Collectors.toMap().

El siguiente fragmento muestra la conversión básica:

ListToMapBasic.java
repos.stream().collect(Collectors.toMap(Repository::name, Function.identity()));

El primer paso es convertir la lista en un Stream y después recoger los resultados usando Collectors.toMap().

Para la clave del Map, usamos Repository::name (una referencia a método equivalente a r -> r.name()). Para el valor del Map, usamos Function.identity() que devuelve el mismo elemento (equivalente a r -> r).

Importante

Si la lista contiene claves duplicadas, lanzará un IllegalStateException. Consulta la siguiente sección para manejar duplicados.

Lista a Mapa con claves duplicadas

Cuando la lista pueda contener claves duplicadas, usa la versión de tres argumentos de toMap() que incluye una función de fusión.

El siguiente fragmento muestra cómo manejar duplicados:

ListToMapWithDuplicates.java
repos.stream().collect(Collectors.toMap(
    Repository::name,
    Function.identity(),
    (existente, nuevo) -> nuevo
));

El tercer parámetro es un BinaryOperator que recibe ambos valores cuando se encuentra una clave duplicada. En este ejemplo, conservamos el valor más nuevo (nuevo), pero podrías:

  • Conservar el primer valor: (existente, nuevo) -> existente
  • Combinar valores: (existente, nuevo) -> fusionarRepositorios(existente, nuevo)
  • Lanzar una excepción: (existente, nuevo) -> { throw new IllegalStateException("Clave duplicada"); }

Lista a Mapa preservando orden de inserción

Por defecto, Collectors.toMap() crea un HashMap, que no preserva el orden de inserción. Para mantener el orden de los elementos de la lista original, usa un LinkedHashMap.

El siguiente fragmento muestra cómo preservar el orden de inserción:

ListToMapOrdered.java
LinkedHashMap<String, Repository> map = repos.stream().collect(Collectors.toMap(
    Repository::name,
    Function.identity(),
    (existente, nuevo) -> existente,
    LinkedHashMap::new
));

El cuarto parámetro es un Supplier que proporciona la implementación del Map. LinkedHashMap mantiene una lista doblemente enlazada de entradas, preservando el orden de iteración.

Lista a Mapa manteniendo orden de claves

Para ordenar las claves alfabéticamente, usa un TreeMap que implementa SortedMap.

El siguiente fragmento muestra cómo ordenar las claves:

ListToMapOrdered.java
TreeMap<String, Repository> ordenado = repos.stream().collect(Collectors.toMap(
    Repository::name,
    Function.identity(),
    (existente, nuevo) -> existente,
    TreeMap::new
));

Para orden alfabético inverso, proporciona un Comparator al constructor de TreeMap:

ListToMapOrdered.java
repos.stream().collect(Collectors.toMap(
    Repository::name,
    Function.identity(),
    (existente, nuevo) -> existente,
    () -> new TreeMap<>(Comparator.reverseOrder())
));

Creando mapas inmutables

Desde Java 10, puedes usar Collectors.toUnmodifiableMap() para crear un mapa inmutable directamente.

El siguiente fragmento muestra cómo crear un mapa inmutable:

ListToMapUnmodifiable.java
Map<String, Repository> mapaInmutable = repos.stream()
    .collect(Collectors.toUnmodifiableMap(Repository::name, Function.identity()));

Cualquier intento de modificar este mapa lanzará un UnsupportedOperationException. Esto es útil para crear estructuras de datos de solo lectura y garantizar la seguridad en entornos multi-hilo.

Consejo

También existe una versión con función de fusión para manejar claves duplicadas: toUnmodifiableMap(keyMapper, valueMapper, mergeFunction).

Manejo de valores nulos

Advertencia

Collectors.toMap() lanza un NullPointerException cuando la función de valor devuelve null. Esto se debe a que internamente usa HashMap.merge() que no acepta valores nulos.

// ¡Esto lanza NullPointerException si description es null!
repos.stream().collect(Collectors.toMap(Repository::name, Repository::description));

Existen varias soluciones alternativas (ver ListToMapNullHandling.java para ejemplos completos):

Opción 1: Usar un bucle tradicional con HashMap.put()

ListToMapNullHandling.java
Map<String, String> map = new HashMap<>();
repos.forEach(repo -> map.put(repo.name(), repo.description()));

Opción 2: Reemplazar nulos con un valor por defecto

ListToMapNullHandling.java
repos.stream().collect(Collectors.toMap(
    Repository::name,
    repo -> repo.description() != null ? repo.description() : "Sin descripción"
));

Opción 3: Filtrar valores nulos antes de recoger

ListToMapNullHandling.java
repos.stream()
    .filter(repo -> repo.description() != null)
    .collect(Collectors.toMap(Repository::name, Repository::description));

Cuándo usar toMap() vs groupingBy()

Usa Collectors.toMap() cuando:

  • Cada elemento se mapea a exactamente un par clave-valor
  • Las claves deben ser únicas (o proporcionarás una función de fusión)

Usa Collectors.groupingBy() cuando:

  • Múltiples elementos comparten la misma clave
  • Quieres una estructura Map<K, List<V>>
// groupingBy: agrupa múltiples repositorios por el flag fork
Map<Boolean, List<Repository>> porFork = repos.stream()
    .collect(Collectors.groupingBy(Repository::fork));

Conclusión

En este artículo, te he mostrado cómo convertir un List a un Map usando Java Streams con Collectors.toMap(). Puntos clave:

  • Usa la versión básica de dos argumentos de toMap() para claves únicas
  • Añade una función de fusión para manejar duplicados
  • Usa LinkedHashMap para preservar el orden de inserción
  • Usa TreeMap para claves ordenadas
  • Usa toUnmodifiableMap() para mapas inmutables (Java 10+)
  • Ten cuidado con NullPointerException cuando hay valores nulos

Puedes encontrar el código fuente completo de este artículo en GitHub.

Java Streams
Java Streams
Twitter iconFacebook iconLinkedIn iconPinterest iconEmail icon

Navegador de artículos
Java 10: Probando las nuevas funcionalidadesSpring Data MongoDB: Implementación de un repositorio a medida
© 2007 - 2026 Marc Nuri