# Why toSortedMap changing size of the original map?

Let’s review simple example:

``````val map = mapOf<String, Int>("test1" to 1, "test2" to 2)

val sorted = map.toSortedMap { a, b ->
map[b]?.compareTo(map[a] ?: 0) ?: 0
}
println(sorted)
``````

The output will be `{test2=2, test1=1}`

Then if we change to

``````val map = mapOf<String, Int>("test1" to 1, "test2" to 1)

val sorted = map.toSortedMap { a, b ->
map[b]?.compareTo(map[a] ?: 0) ?: 0
}
println(sorted)
``````

Then the size of sorted map suddenly shrink to 1 instead of 2 and show output:
`{test1=1}`

in an other hand if I sort map like this:
`val sorted = map.toSortedMap()`
it will keep sorted map size to original 2 elements with output:
`{test1=1, test2=1}`

Can anyone explain why?

Take a closer look into the `TreeMap` implementation. This map doesn’t use `hashCode()` & `equals()` to verify equality of the elements, but the result of comparison itself. The comparison value of `0` means that both elements are equal in this situation, therefore ‘duplicates’ are simply cut off.

As for more practical advice how to fix it, it will depend on what you what to achieve from API perspective.

1 Like

My guess is that you wanted a map-like structure where you access elements via `String` keys with constant time, but when iterating you want an order going by values? You can for example implement map like this:

``````class MapSortedByValues<K, V : Comparable<V>>(sourceMap: Map<K, V>) : Map<K, V> {
private val orderedEntries = sourceMap.entries.sortedBy(Map.Entry<K, V>::value)
private val indexMap = orderedEntries.withIndex().associate { (index, entry) -> entry.key to index }
private val orderedValues = orderedEntries.map(Map.Entry<K, V>::value)

override val entries get() = object : Set<Map.Entry<K, V>> {
override val size get() = orderedEntries.size

override fun contains(element: Map.Entry<K, V>) = element in orderedEntries

override fun containsAll(elements: Collection<Map.Entry<K, V>>) = orderedEntries.containsAll(elements)

override fun isEmpty() = orderedEntries.isEmpty()

override fun iterator() = orderedEntries.iterator()
}

override val keys get() = indexMap.keys

override val size get() = indexMap.size

override val values get() = orderedValues

override fun containsKey(key: K) = key in indexMap

override fun containsValue(value: V) = value in orderedValues

override fun get(key: K) = indexMap[key]?.let(orderedValues::get)

override fun isEmpty() = indexMap.isEmpty()

override fun hashCode() = orderedEntries.hashCode()

override fun equals(other: Any?) = this === other || other is MapSortedByValues<*, *> && orderedEntries == other.orderedEntries

override fun toString() = orderedEntries.joinToString(separator = ", ", prefix = "{", postfix = "}") { "\${it.key}=\${it.value}" }
}

fun main() {
val map = mapOf("test1" to 2, "test2" to 1)
println(map)
val sorted = MapSortedByValues(map)
println(sorted)
}
``````