Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin object expressions: Comparator example

This code basically sorts the array in a descending order:

val arrayList = arrayListOf(1, 5, 2)

Collections.sort(arrayList, object : Comparator<Int> {
   override fun compare(x : Int, y: Int) = y - x
})

How in the world does overriding the compare method with y - x works? How does Kotlin know what y - x means to put y before x if y < x?

like image 363
Rafael Saraiva Avatar asked Oct 30 '15 16:10

Rafael Saraiva


People also ask

How do you compare objects in Kotlin?

In Kotlin, == is the default way to compare two objects: it compares their values by calling equals under the hood. Thus, if equals is overridden in your class, you can safely compare its instances using ==. For reference comparison, you can use the === operator, which works exactly the same as == in Java.

How do you sort an Arraylist of objects in descending order in Kotlin?

Using sort() function The sort() function is the recommended way to in-place sort elements of the specified list. The sorting is done according to the natural ordering of its elements. To sort the list in reverse order, switch to the sortDescending() function.

How do you sort an Arraylist of objects in Kotlin?

For sorting the list with the property, we use list 's sortedWith() method. The sortedWith() method takes a comparator compareBy that compares customProperty of each object and sorts it. The sorted list is then stored in the variable sortedList .


2 Answers

This actually has nothing to do with Kotlin. It's related to the Java API's Comparator interface, and how Collections.sort uses it.

From the documentation:

Compares its two arguments for order. Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.

Now let's try this out for the arguments you gave:

  • 1 - 5 = -4 (a negative integer), so 1 is less than 5.
  • 5 - 2 = 3 (a positive integer), so 5 is greater than 2.
  • etc...

Collections.sort doesn't know anything about what y - x means. It simply respects the defined contract of the Comparator interface that any implementor also needs to respect (if it wants to work).

It just so happens that y - x is an implementation that does respect that contract, because Math.

like image 82
eski Avatar answered Oct 02 '22 03:10

eski


Since Comparator is a SAM interface you can write this code more concise using a lambda:

Collections.sort(arrayList, {x : Int, y: Int -> y - x})

Or even

Collections.sort(arrayList) {
    x, y -> y - x
}

since the lambda is the last parameter of the sort function and the datatype of x and y can be inferred.


Taking two objects and having to define a single integer for them is an abstraction of a sort definition. You basically specify in which order those elements would be layed out if sorted.

For sorting integers it might seem like an overkill, but consider having to sort more complex objects for example instances of a class Car.

This class has a colorCode and you want to sort by that:

Collections.sort(cars) {
    car1, car2 -> car1.colorCode - car2.colorCode
}

That is how you would define an order for those objects in an abstract way.

like image 40
Willi Mentzel Avatar answered Oct 02 '22 02:10

Willi Mentzel