6

I know from official documentation that compareBy creates a comparator using the sequence of functions to calculate a result of comparison. The functions are called sequentially, receive the given values a and b and return Comparable objects.

I know how this must be done for normal attributes like the integer value here, but how are boolean conditions handled by compareBy?

In this example, I intended to keep all 4's at the top of the list and then sort in ascending order of values, but I am not sure how this boolean expression helps me do this!

fun main(args: Array<String>) {
    var foo = listOf(2, 3, 4, 1, 1, 5, 23523, 4, 234, 2, 2334, 2)
    
    foo = foo.sortedWith(compareBy({
        it != 4
    },{
        it
    }))
    
    print(foo)
}

Output

[4, 4, 1, 1, 2, 2, 2, 3, 5, 234, 2334, 23523]
Saurabh Kumar
  • 437
  • 1
  • 5
  • 18

2 Answers2

5

Boolean is Comparable

public class Boolean private constructor() : Comparable<Boolean>

So when you're returning it != 4 in compareBy you're using Boolean's sort order i.e. false < true. Your expression is false only when it == 4, and indeed you can see the 4s as the first elements in the output.

gpunto
  • 2,573
  • 1
  • 14
  • 17
2

Your code provides two selectors as a vararg to compareBy :

foo.sortedWith(
        compareBy(
            { it != 4 },
            { it }
        )
)

Digging into the sources we have a Comparator for any two values a and b built up: Comparator { a, b -> compareValuesByImpl(a, b, selectors) }

and finally:

private fun <T> compareValuesByImpl(a: T, b: T, selectors: Array<out (T) -> Comparable<*>?>): Int {
    for (fn in selectors) {
        val v1 = fn(a)
        val v2 = fn(b)
        val diff = compareValues(v1, v2)
        if (diff != 0) return diff
    }
    return 0
}

The last code snippet demonstrates that if all selectors have the same diff, a and b are considered equal otherwise the first selector with diff != 0 wins.

Booleans are comparable. When comparing 4 with any other value, say 2, you will have:

4 != 4 false
2 != 4 true
diff = false.compareTo( true ) == -1

and so, for sorting, 4 is "less" then any value that is not 4

David Soroko
  • 8,521
  • 2
  • 39
  • 51