Suppose I have a list of persons and would like to have Map<String, Person>
, where String is person name. How should I do that in kotlin?
Asked
Active
Viewed 8,335 times
13

Duncan McGregor
- 17,665
- 12
- 64
- 118

Yurii
- 827
- 2
- 13
- 23
-
Related http://stackoverflow.com/q/34639208/97777 – Duncan McGregor Jan 06 '16 at 17:41
-
1Also related: http://stackoverflow.com/q/34642254 – Jayson Minard Jan 06 '16 at 20:36
2 Answers
24
Assuming that you have
val list: List<Person> = listOf(Person("Ann", 19), Person("John", 23))
the associateBy
function would probably satisfy you:
val map = list.associateBy({ it.name }, { it.age })
/* Contains:
* "Ann" -> 19
* "John" -> 23
*/
As said in KDoc, associateBy
:
Returns a
Map
containing the values provided byvalueTransform
and indexed bykeySelector
functions applied to elements of the given array.If any two elements would have the same key returned by
keySelector
the last one gets added to the map.The returned map preserves the entry iteration order of the original array.
It's applicable to any Iterable
.
-
`toMap()` has changed to `toMapBy()` in current Kotlin, can you please update the answer. – Jayson Minard Jan 06 '16 at 03:59
-
For other equivalents between `Stream.collect` and Kotlin, see http://stackoverflow.com/questions/34642254/what-is-the-java-8-stream-collect-equivalent-in-kotlin – Jayson Minard Jan 06 '16 at 20:37
-
@JaysonMinard, thanks, updated the answer, also used another `toMapBy` overload which is closer to `Collectors.toMap`. – hotkey Jan 06 '16 at 21:45
-
1Coudn't find `List.toMapBy`... maybe missing an import. However `.keysToMap {transform(it)}` was exactly what I was looking for to replace `.stream().collect(Collectors.toMap(Function.identity(), {transform(it)}))`. – TWiStErRob Jan 20 '18 at 23:59
-
@TWiStErRob, the `toMapBy` function seems to have been renamed to [`associateBy`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/associate-by.html). Thanks for noticing that, I'll update the answer. – hotkey Jan 21 '18 at 00:52
-
Actually, don't use `keysToMap` or `associateBy(identity(), {...})` (`associateBy` is OK, `identity()` is not!), both of these are internal to Jetbrains (`org.jetbrains.kotlin.utils`), not public Kotlin API (`kotlin.*`). They lurked in via `gradle-kotlin-dsl` and `kotlin-compiler-embeddable`. Depending on these may cause ClassNotFoundExceptions. – TWiStErRob Jan 22 '18 at 00:26
4
Many alternatives in Kotlin :)
val x: Map<String, Int> = list.associate { it.name to it.age }
val y: Map<String, Int> = list.map { it.name to it.age }.toMap()
var z: Map<String, Int> = list.associateBy({ it.name }, { it.age })
The best option for this particular case IMO is the first as Lambdas are not needed but simple transformation.

Juan Rada
- 3,513
- 1
- 26
- 26