![]() |
VOOZH | about |
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.
At the core of every comparator is the compare function. 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): IntThis function returns 0 if a and b are equal, a negative number if a comes before b and a positive number if a comes after b.
1. reversed():
If we have a comparator but want to reverse the order (e.g., from ascending to descending), we can use the reversed() function.
fun <T> Comparator<T>.reversed(): Comparator<T>
It returns a new comparator with the reverse order.
2. then():
Sometimes, the first comparison may not decide the order (e.g., two people have the same first name). In such cases, we can add a second comparator using then().
infix fun <T> Comparator<T>.then(
comparator: Comparator<in T>
): Comparator<T>
This means: "First compare by A, but if A is equal, then compare by B".
Example:
Output:
Original List:
[Player(firstName=Steve, lastName=Waugh), Player(firstName=Steve, lastName=Smith), Player(firstName=Virat, lastName=Kohli), Player(firstName=Kane, lastName=Williamson), Player(firstName=Joe, lastName=Root)]
Sorted by First Name:
[Player(firstName=Joe, lastName=Root), Player(firstName=Kane, lastName=Williamson), Player(firstName=Steve, lastName=Waugh), Player(firstName=Steve, lastName=Smith), Player(firstName=Virat, lastName=Kohli)]
Sorted by First Name then Last Name:
[Player(firstName=Joe, lastName=Root), Player(firstName=Kane, lastName=Williamson), Player(firstName=Steve, lastName=Smith), Player(firstName=Steve, lastName=Waugh), Player(firstName=Virat, lastName=Kohli)]
Reversed Order:
[Player(firstName=Virat, lastName=Kohli), Player(firstName=Steve, lastName=Waugh), Player(firstName=Steve, lastName=Smith), Player(firstName=Kane, lastName=Williamson), Player(firstName=Joe, lastName=Root)]
These functions allow us to easily chain comparisons based on properties that implement Comparable:
fun <T> Comparator<T>.thenBy(
selector: (T) -> Comparable<*>?
): Comparator<T>
Example:
Output:
Sorted by Height then Weight:
[Box(height=2, weight=10), Box(height=3, weight=25), Box(height=3, weight=45), Box(height=4, weight=10), Box(height=5, weight=50), Box(height=7, weight=95)]
Sorted by Weight then Height Descending:
[Box(height=4, weight=10), Box(height=2, weight=10), Box(height=3, weight=25), Box(height=3, weight=45), Box(height=5, weight=50), Box(height=7, weight=95)]
These give even more control by allowing us to define custom comparison logic as a lambda expression.
fun <T> Comparator<T>.thenComparator(
comparison: (a: T, b: T) -> Int
): Comparator<T>
Example:
Output:
Sorted by String then Integer:
[(A, 0), (A, 3), (B, 1), (E, 20), (G, 345), (J, 0)]
Sorted by Integer then String Descending:
[(J, 0), (A, 0), (B, 1), (A, 3), (E, 20), (G, 345)]