84

In Scala, it's just the map function. For example, if hashMap is a hashMap of strings, then you can do the following:

val result : HashMap[String,String] = hashMap.map(case(k,v) => (k -> v.toUpperCase))

In Kotlin, however, map turns the map into a list. Is there an idiomatic way of doing the same thing in Kotlin?

U Avalos
  • 6,538
  • 7
  • 48
  • 81

4 Answers4

176

I don't think one person's opinion counts as idiomatic, but I'd probably use

// transform keys only (use same values)
hashMap.mapKeys { it.key.uppercase() }

// transform values only (use same key) - what you're after!
hashMap.mapValues { it.value.uppercase() }

// transform keys + values
hashMap.entries.associate { it.key.uppercase() to it.value.uppercase() }

Note: or toUpperCase() prior to Kotlin 1.5.0

James Bassett
  • 9,458
  • 4
  • 35
  • 68
  • 6
    This is what I would do too although if you are only transforming values then you can use `mapValues` instead (e.g. `hashMap.mapValues { it.value.toUpperCase() }`) but I personally don't like the signature of `mapValues` because it uses `transform: (Map.Entry) -> R` instead of `transform: (V) -> R` which seems to me to be inconsistent with `filterValues(predicate: (V) -> Boolean)` meaning you can't write `hashMap.mapValues(String::toUpperCase)` so I just use `hashMap.entries.associate { ... }`. – mfulton26 Feb 07 '17 at 14:39
  • Updated to include `mapValues()` as well, thanks @mfulton26 – James Bassett Feb 07 '17 at 19:37
  • The last line is beautiful. Thank you for this example, Kotlin is indeed awesome. – Lucas P. Dec 09 '20 at 18:49
31

The toMap function seems to be designed for this:

hashMap.map { (key, value) ->
      key.toLowerCase() to value.toUpperCase()
    }.toMap()

It converts Iterable<Pair<K, V>> to Map<K, V>

emu
  • 1,597
  • 16
  • 20
7

You could use the stdlib mapValues function that others have suggested:

hashMap.mapValues { it.value.uppercase() }

or with destructuring

hashMap.mapValues { (_, value) -> value.uppercase() }

I believe this is the most idiomatic way.

Ruckus T-Boom
  • 4,566
  • 1
  • 28
  • 42
-3

I found another variant. It seems to be more clear

val result = mapOf( *hashMap.map { it.key.toUpperCase() to it.value.toUpperCase() }.toTypedArray() ) 

It'll automatically infer the type of resulted map.

.toTypedArray() is required to use splat(*) operator.

braX
  • 11,506
  • 5
  • 20
  • 33