Kotlin - Map

Introducció

Un Map és un conjunt de parelles clau-valor, en què es pot accedir a un valor a partir de la seva clau.

Recuperar claus i valors

A continuació tens un mapa immutable amb 3 parells clau-valor:

val pets = mapOf(1 to "Toby", 4 to "Garfield", 7 to "Snoopy")

Per recuperar un valor d’un mapa has de proporcionar la seva clau amb [] (o la funció get()).

require(pets[4] == "Garfield")

Si no es troba la clau donada, retorna null.

require(pets[2] == null)

Per gestionar claus inexistents, pots utilitzar un valor per defecte:

require(pets.getOrDefault(2, "No pet") == "No pet")

O executar una funció que retorni un valor per defecte:

require(pets.getOrElse(2) { "no pet".uppercase() } == "NO PET")

Per efectuar operacions sobre totes les claus o tots els valors d’un mapa, pots recuperar-los de les propietats keys i values respectivament.

  • keys és un conjunt de totes les claus del mapa
  • values és una col·lecció de tots els valors del mapa.
Activitat

A continuació tens un map amb 3 telefons:

val phoneBook = mapOf(
"Raquel" to 629510476,
"Joan" to 670434123,
"Laura" to 621987345
)

Quin és el telèfon de “Laura”?

Operacions d’escriptura

Els mapes mutables ofereixen operacions d’escriptura específiques per a mapes.

Aquestes operacions permeten canviar el contingut del mapa utilitzant l’accés basat en claus als valors.

Hi ha certes regles que defineixen les operacions d’escriptura en mapes:

  • Els valors es poden actualitzar.

  • Les claus mai canvien: una vegada afegeixes una entrada, la seva clau és constant.

  • Per a cada clau, sempre hi ha un únic valor associat amb ella.

  • Pots afegir i eliminar entrades completes.

Afegir i actualitzar entrades

Per afegir un nou parell clau-valor a un mapa mutable, utilitza [] (o put()).

require(pets[2] == null)
pets[2] = "Dumbo"
require(pets[2] == "Dumbo")

També pots utilitzar la sintaxis +=:

require(pets[2] == null)
pets += 2 to "Dumbo"
require(pets[2] == "Dumbo")

Quan es crida amb una clau present al mapa, els operadors sobreescriuen els valors de les entrades corresponents.

pets[3] = "Milú"
pets[3] = "Lassie"
require(pets[3] == "Lassie")

Eliminar entrades

Per eliminar una entrada d’un mapa mutable, utilitza -= (o remove())

pets[3] = "Milú"
pets -= 3
require(pets[3] == null)

Exemples

Cistella de la compra

Aquí tens un exemple de com podeu utilitzar un mapa per emmagatzemar preus de productes i després calcular el cost total d’una cistella de la compra:

val productPrices = mapOf("Milk" to 1.99, "Bread" to 2.49, "Apple" to 0.35)
val cart = listOf("Milk", "Apple", "Milk", "Bread")
val totalCost = cart.sumByDouble { product -> productPrices[product] ?: 0.0 }
println("Total cost: $totalCost")

En aquest programa Kotlin,

  • productPrices és un mapa de només lectura que conté productes com a claus i els seus preus com a valors.
  • La llista cart representa els articles d’una cistella de la compra.

A continuació, calculem el totalCost iterant sobre la cistella i sumant els preus dels productes. L’operador ?: s’utilitza per gestionar els casos on un producte podria no existir al mapa, assignant-li un valor per defecte de 0.0

Suposem que vols agrupar una llista de persones per la seva edat:

data class Person(val name: String, val age: Int)
fun main() {
val people = listOf(Person("Alice", 29), Person("Bob", 29), Person("Charlie", 25))
val peopleByAge: Map<Int, List<Person>> = people.groupBy { it.age }
require(peopleByAge[29] == listOf(Person("Alice", 29), Person("Bob", 29)))
}

L’ús de la funció groupBy retorna un nou mapa on cada clau és una edat, i el valor és una llista de tots els objectes Person amb aquella edat.

Aquest és un mètode eficient per classificar ràpidament les teves dades basant-te en certs atributs.