Skip to main content

Colecciones Inmutables

⏱ Dedicación recomendada: 0 minutos
Esto considera el contenido visible y relevante, e ignora texto colapsado o marcado como opcional.


r8vnhill/collections-kt

Kotlin ofrece una amplia variedad de colecciones inmutables que permiten gestionar datos de manera eficiente sin modificar su estado. Estas colecciones garantizan la seguridad en situaciones donde no se desea que los datos cambien después de ser inicializados, proporcionando inmutabilidad por defecto.

📌 Diferenciación entre Collection y Map

En muchos lenguajes, como Java, los mapas (Map) forman parte de la jerarquía de colecciones y, en algunos casos, se consideran iterables. Sin embargo, Kotlin hace una distinción clara entre colecciones iterables (Collection) y diccionarios (Map).

🔹 Collection (List, Set) vs Map en Kotlin

TipoOrdenDuplicadosAcceso
ListÍndice
SetNoNoContenido
MapNoClaves únicasClave
  • Collection<E> representa un conjunto de elementos de tipo E que pueden recorrerse secuencialmente. Esto incluye List<E> (listas ordenadas) y Set<E> (conjuntos sin duplicados).
  • Map<K, V> almacena pares clave-valor (K -> V) y no hereda de Collection, ya que su estructura y forma de acceso son distintas.
val lista: List<String> = listOf("Kotlin", "Scala", "Java")
val mapa: Map<String, Int> = mapOf("Kotlin" to 1, "Scala" to 2)

println(lista[0]) // Acceso por índice
println(mapa["Kotlin"]) // Acceso por clave

❓ ¿Por qué Map no es una Collection en Kotlin?

  1. No es iterable de la misma manera

    • Una Collection permite recorrer elementos directamente (for (x in collection)).
    • Un Map requiere iterar sobre keys, values o entries.
    for (entry in mapa) { // ❌ Error: Map<K, V> no es Iterable
    println(entry)
    }

    for ((clave, valor) in mapa.entries) { // ✅ Forma correcta
    println("$clave -> $valor")
    }
  2. Distinta estructura de acceso

    • En Collection, los elementos se acceden secuencialmente (list[index]).
    • En Map, los valores se acceden por clave (map[key]).
  3. Diferente semántica en métodos comunes

    • Collection.contains(element) busca un valor específico.
    • Map.contains(key) verifica si existe una clave.
    println(lista.contains("Kotlin"))  // true
    println(mapa.containsKey("Kotlin")) // true
    println(mapa.containsValue(1)) // true

🔀 Covarianza en Colecciones

Las colecciones son covariantes, lo que permite asignar una colección de un tipo a una colección de su supertipo. Aunque algunos métodos podrían requerir contravarianza, Kotlin los permite siempre y cuando no modifiquen la colección, ya que son métodos de solo lectura, como contains.

Más detalles sobre covarianza

Al asignar una colección de tipo Collection<String> a una variable de tipo Collection<Any>, se pierde la información específica de los tipos, pero algunas operaciones como contains siguen siendo seguras debido a su naturaleza pura (no modifican el estado).

val strings: Collection<String> = listOf("Kotlin", "Java")
val anys: Collection<Any> = strings
println(anys.contains(420)) // Output: false
println(strings.contains(420)) // Error de compilación
¿Qué acabamos de hacer?
  • [2]: La asignación es válida debido a la covarianza: Collection<String> es un subtipo de Collection<Any>.
  • [3]: Aunque 420 no es un String, el método contains espera un Any en anys, lo que permite la llamada. El resultado es false, ya que 420 no está en la colección.
  • [4]: Al intentar usar contains directamente en strings con un Int, el compilador arroja un error porque espera un parámetro de tipo String.

La covarianza en colecciones permite flexibilidad al tratar con tipos genéricos sin comprometer la seguridad de los tipos en operaciones de solo lectura.

⚖️ Ventajas y Desventajas de las Colecciones Inmutables

Beneficios

  • Seguridad en concurrencia: No pueden modificarse, evitando condiciones de carrera.
  • Código más claro y mantenible: Se evitan errores por modificaciones accidentales.
  • Garantía de integridad de datos: Los valores no cambian después de ser inicializados.

Limitaciones

  • Menor flexibilidad: Cada modificación requiere crear una nueva colección.
  • Mayor uso de memoria: Si hay muchas modificaciones, puede ser menos eficiente.

🎯 Conclusiones

Las colecciones inmutables en Kotlin permiten gestionar datos de forma segura y predecible, garantizando que no se modifiquen accidentalmente una vez inicializadas. A lo largo de esta lección, hemos explorado sus características y diferencias con otras estructuras de datos.

Puntos clave

  • Diferenciación entre Collection y Map
    • A diferencia de otros lenguajes, Kotlin trata Map como una estructura separada, no como parte de Collection, debido a sus diferencias en iterabilidad y acceso.
  • Covarianza en colecciones
    • Las colecciones en Kotlin son covariantes, lo que permite mayor flexibilidad en la manipulación de tipos genéricos sin comprometer la seguridad en operaciones de solo lectura.
  • Beneficios de la inmutabilidad
    • Se evitan modificaciones inesperadas, lo que hace que el código sea más predecible y fácil de mantener.
    • Son ideales para entornos concurrentes, ya que eliminan problemas de sincronización.
  • Limitaciones de las colecciones inmutables
    • En escenarios donde se requieren modificaciones frecuentes, pueden resultar menos eficientes en términos de memoria y rendimiento.

✅ Cuándo usarlas

  • Cuando la estabilidad y la seguridad son prioridad, como en concurrencia o en estructuras de datos compartidas.
  • Para mejorar la mantenibilidad del código, evitando estados mutables difíciles de rastrear.
  • En funciones puras, donde se busca garantizar que los datos no se alteren.

⚠️ Alternativas cuando se requiere mutabilidad

  • Si se necesitan modificaciones frecuentes, MutableList, MutableSet y MutableMap pueden ser opciones más eficientes.
  • Si la eficiencia en memoria es una prioridad, en algunos casos las colecciones mutables pueden reducir la sobrecarga de creación de nuevas instancias.

En general, usar colecciones inmutables por defecto y recurrir a estructuras mutables solo cuando sea estrictamente necesario es una buena práctica en Kotlin.

Bibliografías Recomendadas

Bibliografías Adicionales

  • 📚 "Chapter 9. Collections: Get Organized". (2019). Dawn Griffiths & David Griffiths, en Head First Kotlin, (pp. 439-502.) O’Reilly.