Is there any particular reason there is no `toMap(...
# stdlib
s
Is there any particular reason there is no
toMap()
function available as an extension on a collection of
Map.Entry<K, V>
?
a
@sxtanna JDK documentation says
These Map.Entry objects are valid only for the duration of the iteration; more formally, the behavior of a map entry is undefined if the backing map has been modified after the entry was returned by the iterator
(https://docs.oracle.com/javase/8/docs/api/java/util/Map.Entry.html). That means you are not able to create a new Map from
List<Map.Entry<K, V>>
, because they are short-lived instances. So you need to create new `Pair<K, V>`s and use them to construct a new map
Take a look at this
What concerns me is that is it not directly possible to create this flow without having to create a duplicate pairing for each entry within the map
This Entry set's stream can be directly collected into a map from the entries themselves
This should be possible using the stdlib, especially considering the massive amount of extensions on collections that remove the need for the Stream api
@Andreas Sinz
a
@sxtanna creating short-lived `Pair<K, V>`s is the functional way to do it. you can easily create an imperative version:
Copy code
fun <K, V, R, T> Iterator<Map.Entry<K, V>>.toMap(keyTransform: (K) -> R, valueTransform: (V) -> T): Map<R, T> {
    var map = mutableMapOf<R, T>()
    this.forEach { entry ->
        map.put(keyTransform(entry.key), valueTransform(entry.value))
    }

    return map
}
s
@Andreas Sinz Exactly what would be the problem with the stdlib having a function
Copy code
fun <K, V> Iterable<Map.Entry<K, V>>.toMap() : Map<K, V> {
    val map = mutableMapOf<K, V>()
    this.forEach { map.put(it.key, it.value) }
    return map
}
a
do you need to transform the Entries or just create a copy of the map?
s
The entries are in a collection because they have been sorted
I want to be able to create the map from the collections of entries, without having to create another object for every entry
Its redundant
The solution I came up with for the stackoverflow question in Kotlin is this
Copy code
map.entries.sortedBy { it.key }.sortedBy { it.value }
But this leaves you with
List<Map.Entry<K, V>>
Which you would then need to map to
List<Pair<K, V>>
in order to access the
toMap()
function
a
do you need to sort by key only, or by key and value?
s
Uhh
The Map needs to be sorted by both key and value
All same values should be grouped, with the keys being sorted
a
ok, then the only option right now is to use your own method. I dont think theres a problem with this function being in the stdlib, just noone has bothered yet to report it/send a PR
s
Yeah, I already had a working solution, I was just asking here why it doesn't exist
i
@sxtanna Btw, you can use
associate
and
associateBy
extensions to create a map from any iterable, for example:
map.entries.associateBy({ it.key }, { it.value })
s
@ilya.gorbunov Thats nice, however its still much more verbose than a simple
toMap()