In Java we can easily sort a Collecion by enum with something like this:
Collections.sort(toSortEnumList, new Comparator<theEnum>() {
@Override
public int compare(theEnum o1, theEnum o2) {
return o1.ordinal().compareTo(o2.ordinal());
}
});
and the toSortEnumList
will be ordered ascending. How can I do this with a Kotlin's sealed classes? I tried sorting by the class names but that's not by enum position. There must be some way to sort by enum position:
sealed class GoodCountries {
class Brazil : GoodCountries() {}
class USA : GoodCountries() {}
class Germany : GoodCountries() {}
class China : GoodCountries() {}
}
// later on
var toSortList = listOf<GoodCountries>(China(), Brazil(), USA(), Germany())
Collections.sort(
toSortList,
{ x: GoodCountries, y: GoodCountries -> y::class.java.name.compareTo(x::class.java.name) }
)
Log.v("myTag", toSortList.toString())
this prints:
USA, Germany, China, Brazil
descending order. Not what I want. I want to sort by sealed class order (like ordinal number in Java's enum) like this:
Brazil, USA, Germany, China
I thought sealed classes are supposed to be better then enums but if I can't do this maybe enums have an advantage.
UPDATE: Thanks to Roland's help I was able to find the list of sealed classes. but now I want to sort by it: here is what I have so far:
Collections.sort(toSortList, object : Comparator<GoodCountries> {
override fun compare(left: GoodCountries, right: GoodCountries): Int {
return Integer.compare(
GoodCountries::class.sealedSubclasses.indexOf(left),
GoodCountries::class.sealedSubclasses.indexOf(right)
)
}
})
but I get the following error at indexOf
:
Type inference failed. The value of the type parameter T should be mentioned in input types (argument type, receiver type or expected type). Try to specify it explicitely.
You could give your GoodCountries
an order
property like so:
sealed class GoodCountries(val order: Int) {
class Brazil : GoodCountries(0)
class USA : GoodCountries(1)
class Germany : GoodCountries(2)
class China : GoodCountries(3)
}
It's not a perfect solution since you have to enumerate by hand, but this way the desired order is guaranteed.
Doing this would simplify your comparison code dramatically:
val sorted = toSortList.sortedBy(GoodCountries::order)
println(sorted.map { it::class.simpleName })
Output:
[Brazil, USA, Germany, China]
Edit: Updated with great idea of Chrispher which made the code even cleaner (having order
property in constructor of GoodCountries
instead of making it an abstract variable which is overriden by the subclasses).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With