Mapas En Kotlin

ANUNCIO
Loading...

En este tutorial verás la definición y uso de mapas en Kotlin. Verás la declaración de la interfaz Map, como crear mapas de solo lectura, mapas mutables y como iterar sobre sus entradas en un bucle for.

Mapas

Un mapa es una colección que almacena sus elementos (entradas) en forma de pares clave-valor.

Esto quiere decir que a cada clave le corresponde un solo valor y será única como si se tratase de un identificador.

Ilustración de mapas en Kotlin

La ilustración anterior muestra la correspondencia entre una colección de claves a una de valores. Por ejemplo, la entrada «Name» -> «Catrina sería un habitante del mapa.

Crear Mapas De Solo Lectura

La interfaz que representa a los mapas en Kotlin es Map<K,V>. Donde los parámetros de tipo K y V representan a los tipos para claves (propiedad keys) y valores (propiedad values).

interface Map<K, out V>
Lenguaje del código: Kotlin (kotlin)

Esta definición solo te provee acceso de solo lectura, por lo que solo podrás usar comportamientos de consulta.

Para crear un mapa de solo lectura usa una de las formas de la función mapOf():

// Múltiples pares fun <K, V> mapOf(vararg pairs: Pair<K, V>): Map<K, V> // Mapa vacío fun <K, V> mapOf(): Map<K, V> // Un solo par fun <K, V> mapOf(pair: Pair<K, V>): Map<K, V>
Lenguaje del código: Kotlin (kotlin)

Como ves, las entradas del mapa se generan con la clase Pair, la cual representa un par de valores genérico.

Por ejemplo, si creas un mapa para cargar los ajustes de un usuario en tu aplicación:

fun main() { val userSettings: Map<String, String> = mapOf( "name" to "Catrina", "language" to "Español", "logo" to "logo.png", "website" to "www.site.com" ) println("$userSettings") // {name=Catrina, language=Español, logo=logo.png, website=www.site.com} }
Lenguaje del código: Kotlin (kotlin)

La función de extensión to() usa el modificador infix para permitirte crear pares de forma legible:

infix fun <A, B> A.to(that: B): Pair<A, B>
Lenguaje del código: Kotlin (kotlin)

Sin embargo, también es posible crear el par con el constructor de la forma Pair("name", "Catrina").

Operaciones De Lectura

Los siguientes son atributos y métodos que te permiten consultar el estado de tus mapas:

  • entries: retorna un tipo Set<Entry<K,V>> de solo lectura de todos los pares clave-valor
  • keys: retorna un Set<K> de solo lectura de todas las claves
  • size: retorna el número de entradas en el mapa
  • values: retornar una Collection<V> de solo lectura con los valores en el mapa

Si imprimes todas las propiedades del ejemplo anterior tendrás lo siguiente:

println(userSettings.size) // 4 println(userSettings.entries) // [name=Catrina, language=Español, logo=logo.png, website=www.site.com] println(userSettings.keys) // [name, language, logo, website] println(userSettings.values) // [Catrina, Español, logo.png, www.site.com]
Lenguaje del código: Kotlin (kotlin)

Por el lado de los métodos de lectura tienes a:

  • mapa[clave]: Esta sintaxis permite obtener el valor a partir de la clave en el corchete. Es la construcción equivalente al operador get(clave)
  • getOrDefault(key, defaultValue): Obtiene el valor correspondiente a la clave, de lo contrario retorna a defaultValue
  • isEmpty(): Retorna true si el mapa no contiene entradas y false en caso contrario
  • containsKey(key): Retorna true si key existe en el mapa. Esto es equivalente a usar el operador in al comprar la clave frente al mapa
  • containsValue(value): Retorna true si una o varias claves se relacionan con value

Observa algunos ejemplos:

println(userSettings["logo"]) // logo.png println(userSettings.get("web")) // null println(userSettings.getOrDefault("email", "Sin email")) // Sin email println(userSettings.isEmpty()) // false println("name" in userSettings) // true println("Español" in userSettings.values ) // true
Lenguaje del código: Kotlin (kotlin)

El tipo de retorno del operador get() es anulable, por lo que si no encuentra el elemento obtendrás null como se muestra en la línea 2.

Tanto containsKey() como containsValue() pueden reemplazarse con el operador in.

Crear Mapas Mutables

Los mapas mutables te otorgan el poder de usar comandos de operaciones sobre los elementos como agregar, actualizar y remover entradas. El diseño de esta figura la encuentras en la interfaz MutableMap<K,V>, la cual extiende de Map<K,V>.

interface MutableMap<K, V> : Map<K, V>
Lenguaje del código: Kotlin (kotlin)

Crea una instancia de un mapa mutable con el método mutableMapOf(). Al igual que mapOf() recibe argumentos variables para los pares iniciales, o puedes crear una definición vacía:

fun <K, V> mutableMapOf(): MutableMap<K, V> fun <K, V> mutableMapOf( vararg pairs: Pair<K, V> ): MutableMap<K, V>
Lenguaje del código: Kotlin (kotlin)

Por ejemplo, creemos un mapa que contenga el año de publicación de varios libros:

fun main() { val booksMap = mutableMapOf( "Sinsajo" to 2010, "Yo, Robot" to 1950, "Crimen y castigo" to 1935, "Cien años de soledad" to 1991 ) println(booksMap) // {Sinsajo=2010, Yo, Robot=1950, Crimen y castigo=1935, Cien años de soledad=1991} }
Lenguaje del código: Kotlin (kotlin)

Veamos como modificar su estructura.

Añadir Y Actualizar Entradas

Usa el método put(key, value) para asociar la clave key con el valor value. Si la clave no existe la entrada es añadida al mapa, de lo contrario el valor es actualizado.

booksMap.put("La máquina del tiempo", 1890) booksMap["La máquina del tiempo"] = 1895 println(booksMap) // {Sinsajo=2010, Yo, Robot=1950, Crimen y castigo=1935, Cien años de soledad=1991, La máquina del tiempo=1895}
Lenguaje del código: Kotlin (kotlin)

Sin embargo IntelliJ IDEA te recomendará usar al operador [ ] junto con la clave para añadir o actualizar.

Remover Entradas

En este caso usa el método remove(key) para remover la entrada del mapa. Por ejemplo, eliminemos la entrada para "Sinsajo":

booksMap.remove("Sinsajo") println(booksMap) // {Yo, Robot=1950, Crimen y castigo=1935, Cien años de soledad=1991, La máquina del tiempo=1895}
Lenguaje del código: Kotlin (kotlin)

Otra variante del método es remove(key, value) donde se remueve el elemento con la clave key solo si su valor actual es value. El retorno será true si es eliminado o false en caso negativo.

println(booksMap.remove("Cien años de soledad", 2015)) // false
Lenguaje del código: Kotlin (kotlin)

Recorrer Un Mapa

Debido a la naturaleza de los mapas en Kotlin, es posible desestructurar las declaraciones que comprometan a sus entradas en valores individuales.

Un ejemplo claro de esto es recorrer sobre los elementos de un mapa en un bucle for:

fun main() { val operationsMap = mapOf( "Suma" to '+', "Resta" to '-', "Multiplicación" to 'x', "División" to '÷' ) for ((operation, symbol) in operationsMap) { println("$operation -> $symbol") } }
Lenguaje del código: Kotlin (kotlin)

Salida:

Suma -> + Resta -> - Multiplicación -> x División -> ÷

Como ves, convertimos a la sintaxis (operation, symbol) cada entrada de operationsMap, con el fin de utilizar ambos elementos en el cuerpo del bucle.

Esto también es aplicable para la declaración de lambdas. Es posible expresar como lista de parámetros el par clave-valor. Por ejemplo, si usamos la función forEach() sobre el mapa para imprimir su contenido:

operationsMap.forEach { (k, v) -> println("$k -> $v") }
Lenguaje del código: Kotlin (kotlin)

Pasamos como sección de parámetros el combinado (k, v) para que el cuerpo del lambda imprima en cada iteración a la entrada.

¿Ha sido útil esta publicación?