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]
CodePudding user response:
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.
CodePudding user response:
Your code provides two selectors as a vararg
to compareBy
:
foo = 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 gets to decide.
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 4 is "less" then any value that is not 4