Search

Dark theme | Light theme

April 2, 2026

Kotlin Kandy: Transform Map Keys Or Values With mapKeys And mapValues

Sometimes you want to transform only the keys in a Map, or only transform the values. Kotlin has two useful methods to achieve this: mapKeys and mapValues. You can use mapKeys to transform the keys of the map while keeping the values the same. With mapValues you can transform the values of the map while keeping the keys the same. Both methods accept a lambda function that receives a Map.Entry as argument and must return the new key or value. In order to transform the keys or values and add the result to an existing Map you can use the methods mapKeysTo and mapValuesTo. The first argument is the existing Map and the second argument is the lambda function.

In the following example we use mapKeys to transform the keys of a map:

// Sample map with language names as keys and their first release year as values.
val languages = mapOf("Kotlin" to 2011, "Groovy" to 2003, "Java" to 1995)

// Use mapKeys to transform the keys to lowercase.
// The lambda receives a Map.Entry with key and value properties.
assert(languages.mapKeys { it.key.lowercase() } ==
         mapOf("kotlin" to 2011, "groovy" to 2003, "java" to 1995))

// You can use destructuring in the lambda to access key and value directly.
assert(languages.mapKeys { (key, _) -> key.uppercase() } ==
         mapOf("KOTLIN" to 2011, "GROOVY" to 2003, "JAVA" to 1995))

// You can also use the value property in the lambda
// to create a new key based on the value.
assert(languages.mapKeys { "${it.key} (${it.value})" } ==
         mapOf("Kotlin (2011)" to 2011, "Groovy (2003)" to 2003, "Java (1995)" to 1995))

In the next example we use mapValues to transform the values of a map:

val languages = mapOf("Kotlin" to 2011, "Groovy" to 2003, "Java" to 1995)

// Use mapValues to transform the values.
// Calculate the age of the language.
assert(languages.mapValues { 2026 - it.value } ==
         mapOf("Kotlin" to 15, "Groovy" to 23, "Java" to 31))

// Using destructuring in the lambda to access key and value directly.
assert(languages.mapValues { (_, value) -> value * 2 } ==
         mapOf("Kotlin" to 4022, "Groovy" to 4006, "Java" to 3990))

// You can also use the key property to create a new value
// based on both the key and value.
assert(languages.mapValues { "${it.key} was first released in ${it.value}" } ==
         mapOf("Kotlin" to "Kotlin was first released in 2011",
               "Groovy" to "Groovy was first released in 2003",
               "Java" to "Java was first released in 1995"))

We can also use the methods mapKeysTo and mapValuesTo to add the transformed entries to an existing mutable Map instance. The first argument is the mutable Map and the second argument is the lambda function to transform the key or value:

val languages = mapOf("Kotlin" to 2011, "Groovy" to 2003)

// Use mapKeysTo to add transformed entries to an existing mutable map.
val result = languages.mapKeysTo(mutableMapOf("java" to 1995)) { it.key.lowercase() }

assert(result == mapOf("java" to 1995, "kotlin" to 2011, "groovy" to 2003))

// Use mapValuesTo to add transformed entries to an existing mutable map.
val ageResult = languages.mapValuesTo(mutableMapOf("Java" to 31)) { 2026 - it.value }

assert(ageResult == mapOf("Java" to 31, "Kotlin" to 15, "Groovy" to 23))

Written with Kotlin 2.3.20.