Comparator in Kotlin

In programming contexts, as there arises a need for a new type, there is also a major task of ordering the instances of a type. To compare two instances of a type we implement Comparable interface. However, since in ordering instances they must be compared automatically and also since the order can vary according to various parameters, Kotlin provides a simple Comparator interface. This interface compares two objects of a type and arranges them in an order.

Function –

compare: This function compares two instance of a type and returns zero if both are equal, a negative number if second instance is bigger otherwise returns a positive number.

abstract fun compare(a: T, b: T): Int

Extension Functions –

reversed: This function takes a comparator as an argument and returns the comparator with the ordering reversed as that of the passed comparator.



fun <T> Comparator<T>.reversed(): Comparator<T>

 
then: This function combines two comparator, and the second one is used only when the values are equal according to the first comparator.

infix fun <T> Comparator<T>.then(
    comparator: Comparator<in T>
): Comparator<T>

Example to demonstrate the compare, then and reversed functions.

filter_none

edit
close

play_arrow

link
brightness_4
code

// A simple class to represent a name
class Name(val firstName: String,val lastName: String){
    override fun toString(): String {
        return """$firstName $lastName"""
    }
}
   
// A comparator to compare first names of Name
class ComparatorOne: Comparator<Name>{
    override fun compare(o1: Name?, o2: Name?): Int {
        if(o1 == null || o2 == null){
            return 0;
        }
        return o1.firstName.compareTo(o2.firstName)
    }
}
   
// A comparator to compare last names of Name
class AnotherComparator: Comparator<Name>{
    override fun compare(o1: Name?, o2: Name?): Int {
        if(o1 == null || o2 == null)
            return 0
        return o1.lastName.compareTo(o2.lastName)
    }
}
   
fun main(){
    val list = ArrayList<Name>()
    list.add(Name("Steve","Waugh"))
    list.add(Name("Steve","Smith"))
    list.add(Name("Virat","Kohli"))
    list.add(Name("Kane","Williamson"))
    list.add(Name("Joe","Root"))
   
    println("The list is:")
    println(list)
   
    val comparatorOne = ComparatorOne()
    // Sorting list according to first names
    list.sortWith(comparatorOne)
    println("List sorted according to first name")
    println(list)
   
    val anotherComparator = AnotherComparator()
    val finalComparator = comparatorOne.then(anotherComparator)
    // Sorting list according to first name then by last name
    list.sortWith(finalComparator)
    println("List sorted according to first name and last name")
    println(list)
   
    val reverseComparator = finalComparator.reversed()
    // Reverse sorting the list
    list.sortWith(reverseComparator)
    println("List reverse sorted")
    println(list)
}

chevron_right


Output:

The list is:
[Steve Waugh, Steve Smith, Virat Kohli, Kane Williamson, Joe Root]
List sorted according to first name
[Joe Root, Kane Williamson, Steve Waugh, Steve Smith, Virat Kohli]
List sorted according to first name and last name
[Joe Root, Kane Williamson, Steve Smith, Steve Waugh, Virat Kohli]
List reverse sorted
[Virat Kohli, Steve Waugh, Steve Smith, Kane Williamson, Joe Root]

 

thenBy: This function converts the type instances to an instance of type Comparable and then compares them using these instances.

fun <T> Comparator<T>.thenBy(
    selector: (T) -> Comparable<*>?
): Comparator<T>

 
thenByDescending: This function returns a descending comparator which converts a value into an instance of type Comparable and then compares the instances.

inline fun <T> Comparator<T>.thenByDescending(
    crossinline selector: (T) -> Comparable<*>?
): Comparator<T>

Example to demonstrate the thenBy and thenByDescending functions

filter_none

edit
close

play_arrow

link
brightness_4
code

class Person(val height: Int,val weight: Int){
    override fun toString(): String {
        return "Height = ${height}, Weight = ${weight}"
    }
}
   
fun main() {
    val comparator = compareBy<Person> { it.height }
    val list = listOf<Person>(
        Person(4, 10),
        Person(2, 10),
        Person(3, 45),
        Person(3, 25),
        Person(7, 95),
        Person(5, 50)
    )
   
    println("Sorted first according to height then by weight")
    val anotherComparator = comparator.thenBy { it.weight }
    println(list.sortedWith(anotherComparator))
   
    println("Sorted first according to weight then by descending order in height")
    val comparator2 = compareBy<Person> { it.weight }.thenByDescending { it.height }
    println(list.sortedWith(comparator2))
}

chevron_right


Output:

Sorted first according to height then by weight
[Height = 2, Weight = 10, Height = 3, Weight = 25, Height = 3, Weight = 45, Height = 4, Weight = 10, Height = 5, Weight = 50, Height = 7, Weight = 95]
Sorted first according to weight then by descending order in height
[Height = 4, Weight = 10, Height = 2, Weight = 10, Height = 3, Weight = 25, Height = 3, Weight = 45, Height = 5, Weight = 50, Height = 7, Weight = 95]

 
thenComparator: This function returns a Comparator which uses the primary Comparator along with a function to perform a comparison.

fun <T> Comparator<T>.thenComparator(
    comparison: (a: T, b: T) -> Int
): Comparator<T>

 
thenDescending: This function combines two comparator, and the second one is used only when the values are equal according to the first comparator, and sorts the elements in descending order.

infix fun <T> Comparator<T>.thenDescending(
    comparator: Comparator<in T>
): Comparator<T>

Example to demonstrate the thenComparator and thenDescending functions.

filter_none

edit
close

play_arrow

link
brightness_4
code

fun main(){
    val list = listOf<Pair<String,Int>>(
        Pair("A",3),
        Pair("B",1),
        Pair("G",345),
        Pair("E",20),
        Pair("A",0),
        Pair("J",0)
    )
   
    val comparator = compareBy<Pair<String,Int>> { it.first }
        .thenComparator({a,b -> compareValues(a.second,b.second)})
   
    println("Pairs sorted by String then by Integers")
    println(list.sortedWith(comparator))
   
    val anotherComparator = compareBy<Pair<String,Int>> { it.second }
    val anotherComparator2 = compareBy<Pair<String,Int>>{it.first}
    println("Pairs sorted by Integers then by Strings in Descending order")
    println(list.sortedWith(anotherComparator.thenDescending(anotherComparator2)))
}

chevron_right


Output:

Pairs sorted by String then by Integers
[(A, 0), (A, 3), (B, 1), (E, 20), (G, 345), (J, 0)]
Pairs sorted by Integers then by Strings in Descending order
[(J, 0), (A, 0), (B, 1), (A, 3), (E, 20), (G, 345)]


My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.




Article Tags :

Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.