De lista a mapa: ¿por qué es importante y cómo hacerlo correctamente?
\n\nImagine la situación: está trabajando en una aplicación en Kotlin, ha recibido una lista de usuarios desde una API. Necesita encontrar rápidamente un usuario por su ID. Recorrer la lista cada vez es O(n), lo que con 1000+ elementos se convierte en un dolor. En cambio, la búsqueda en un Map es O(1). La diferencia es colosal.
\n\nLa pregunta "How to convert List to Map in Kotlin?" es una de las más populares en Stack Overflow. Y no es para menos: una conversión incorrecta puede provocar pérdida de datos, caída del rendimiento o errores extraños. Hoy analizaremos 5 formas de transformación, desde las simples hasta las avanzadas, y descubriremos cómo acelerar su código 10 veces.
\n\nEnfoques básicos: associate, toMap y groupBy
\n\n1. Clásico: associate — la opción más común
\nLa función associate es el rey de la conversión. Acepta una lambda que devuelve un par (clave, valor).
data class User(val id: Int, val name: String, val age: Int)\n\nval users = listOf(\n User(1, "Ana", 25),\n User(2, "Boris", 30),\n User(3, "Víctor", 22)\n)\n\n// Caso más simple: id -> name\nval idToNameMap: Map<Int, String> = users.associate { it.id to it.name }\nprintln(idToNameMap) // {1=Ana, 2=Boris, 3=Víctor}\n\n// Objeto completo por id\nval userMap: Map<Int, User> = users.associate { it.id to it }\nprintln(userMap[2]) // User(id=2, name="Boris", age=30)\n\n\nImportante: si en la lista hay claves duplicadas (associate simplemente sobrescribirá con la última), ni siquiera lo notará. ¡Tenga cuidado!
2. toMap — cuando ya tiene una colección de pares
\nSi ha creado previamente una lista de pares Pair<K, V>, use toMap().
val pairs = listOf(\n 1 to "Ana",\n 2 to "Boris",\n 3 to "Víctor"\n)\n\nval mapFromPairs: Map<Int, String> = pairs.toMap()\nprintln(mapFromPairs) // {1=Ana, 2=Boris, 3=Víctor}\n\n\ntoMap también funciona con colecciones de Map.Entry y otros iteradores de pares.
3. groupBy — cuando una clave corresponde a varios valores
\nA veces es necesario agrupar elementos por clave. Por ejemplo, agrupar usuarios por edad.
\n\nval usersByAge: Map<Int, List<User>> = users.groupBy { it.age }\n// Resultado: {25=[User(id=1, name=Ana, age=25)], 30=[User(id=2, name=Boris, age=30)], 22=[User(id=3, name=Víctor, age=22)]}\n\n\ngroupBy devuelve un Map<K, List<V>>. Ideal para análisis, filtrado y creación de informes.
Técnicas avanzadas: cuando los métodos estándar no son suficientes
\n\n4. associateBy — si solo necesita la clave y el valor es el propio elemento
\nLa función associateBy es un sinónimo de associate { key to it }, pero se lee mejor.
val userMapById: Map<Int, User> = users.associateBy { it.id }\n// Equivalente a: users.associate { it.id to it }\nprintln(userMapById[1]) // User(id=1, name=Ana, age=25)\n\n\nConsejo: use associateBy cuando necesite crear un diccionario "clave → objeto en sí". El código queda más limpio.
5. Conversión personalizada con manejo de duplicados
\nSupongamos que tiene una lista de pedidos y varios pedidos pueden tener el mismo ID (por ejemplo, versiones diferentes). El associate estándar simplemente sobrescribirá. ¿Y si necesita conservarlos todos?
data class Order(val id: Int, val amount: Double, val version: Int)\n\nval orders = listOf(\n Order(1, 100.0, 1),\n Order(1, 150.0, 2), // id duplicado, pero versión diferente\n Order(2, 200.0, 1)\n)\n\n// Opción 1: agrupación por id\nval ordersGrouped: Map<Int, List<Order>> = orders.groupBy { it.id }\n// {1=[Order(1, 100.0, 1), Order(1, 150.0, 2)], 2=[O