Hi guys... Is there a way to sort a map/Hashmap us...
# announcements
l
Hi guys... Is there a way to sort a map/Hashmap using both the keys and values. For instance:
Copy code
[Elijah=51, Chloe=144, Natalie=207, Jayden=390, Elizabeth=485, Matthew=485]
In this map, I would like values to be sorted in a descending order first. Then sort the keys in an alphabetical order. i.e
Elizabeth
must appear before
Matthew
even though their values are the same. 🤷‍♂️
n
Hashmap can't be sorted at all because of how it works... You can use a TreeMap to define your custom sorting order
m
Copy code
val map = mapOf(
    "Elijah" to 51, "Chloe" to 144, "Natalie" to 207, "Jayden" to 390, "Matthew" to 485, "Elizabeth" to 485,
)
val sortedMap = map
    .toList()
    .sortedWith(compareBy<Pair<String,Int>> { it.second }.thenBy { it.first })
    .toMap()
l
@Marc Knaup, your solution results to
Copy code
{Elijah=51, Chloe=144, Natalie=207, Jayden=390, Elizabeth=485, Matthew=485}
n
(note that the
toMap
does not return a
HashMap
which does not have its fast amortized O(1) look up time)
m
@linus muema I’ve missed the “descending” 🙂
Copy code
val map = mapOf(
    "Elijah" to 51, "Chloe" to 144, "Natalie" to 207, "Jayden" to 390, "Matthew" to 485, "Elizabeth" to 485,
)
val sortedMap = map
    .toList()
    .sortedWith(compareByDescending<Pair<String,Int>> { it.second }.thenBy { it.first })
    .toMap()
@Niklas Gürtler
toMap()
uses
LinkedHashMap
which should also have O(1) lookup. It just uses more memory to maintain order.
l
@Marc Knaup It works...Thanks a lot K
👍 1
n
Right, that's basically a HashMap + Linked list so technically the HashMap is still not sorted 😉 but right, that's a good solution
i
Could it be a bit simplified using
entries
instead of intermediate
toList
?
m
Then you won’t have a convenient
toMap()
at the end which operates on
Iterable<Pair<…>>
i
Got it, thank you
m
@Ivan Pavlov it would look like this:
Copy code
val sortedMap = map
        .entries
        .sortedWith(compareByDescending<Map.Entry<String, Int>> { it.key }.thenBy { it.value })
        .associate { it.key to it.value }
i
Personally I prefer associateBy version which doesn't create intermediate pairs for each entry too :)
m
associateBy
only allows you to specify the key, not the value.
i
No, there is overload which accepts both keySelector and valueTransform
m
Ah yeah, you’re right 🙂