diff --git a/libraries/stdlib/src/kotlin/util/Ordering.kt b/libraries/stdlib/src/kotlin/util/Ordering.kt index 9fd78bea4bd..4e9da59a4a5 100644 --- a/libraries/stdlib/src/kotlin/util/Ordering.kt +++ b/libraries/stdlib/src/kotlin/util/Ordering.kt @@ -75,7 +75,7 @@ public fun > compareValues(a: T?, b: T?): Int { if (a == null) return -1 if (b == null) return 1 - return (a as Comparable).compareTo(b) + return (a as Comparable).compareTo(b) } /** @@ -293,9 +293,21 @@ public fun > nullsLast(): Comparator { } } +/** + * Returns a comparator that compares [Comparable] objects in natural order. + */ +public fun > naturalOrder(): Comparator = NaturalOrderComparator as Comparator + +/** + * Returns a comparator that compares [Comparable] objects in reversed natural order. + */ +public fun > reverseOrder(): Comparator = ReverseOrderComparator as Comparator + /** Returns a comparator that imposes the reverse ordering of this comparator. */ public fun Comparator.reversed(): Comparator = when (this) { is ReversedComparator -> this.comparator + NaturalOrderComparator -> ReverseOrderComparator as Comparator + ReverseOrderComparator -> NaturalOrderComparator as Comparator else -> ReversedComparator(this) } @@ -303,3 +315,11 @@ public fun Comparator.reversed(): Comparator = when (this) { private class ReversedComparator(public val comparator: Comparator): Comparator { override fun compare(a: T, b: T): Int = comparator.compare(b, a) } + +private object NaturalOrderComparator : Comparator> { + override fun compare(c1: Comparable, c2: Comparable): Int = c1.compareTo(c2) +} + +private object ReverseOrderComparator: Comparator> { + override fun compare(c1: Comparable, c2: Comparable): Int = c2.compareTo(c1) +} diff --git a/libraries/stdlib/test/OrderingTest.kt b/libraries/stdlib/test/OrderingTest.kt index fbf61f25e5f..60558e8b93f 100644 --- a/libraries/stdlib/test/OrderingTest.kt +++ b/libraries/stdlib/test/OrderingTest.kt @@ -50,7 +50,7 @@ class OrderingTest { @Test fun sortComparatorThenComparator() { - val comparator = comparator { a, b -> a.name.compareTo(b.name) } thenComparator { a, b -> a.rating.compareTo(b.rating) } + val comparator = comparator { a, b -> a.name.compareTo(b.name) }.thenComparator { a, b -> a.rating.compareTo(b.rating) } val diff = comparator.compare(v1, v2) assertTrue(diff > 0) @@ -74,9 +74,28 @@ class OrderingTest { assertTrue( (byRating thenDescending byName).compare(v4, v2) < 0 ) } + @Test + fun reversedComparator() { + val comparator = compareBy { it.name } + val reversed = comparator.reversed() + assertEquals(comparator.compare(v2, v1), reversed.compare(v1, v2)) + assertEquals(comparator, reversed.reversed()) + } + + @Test + fun naturalOrderComparator() { + val v1 = "a" + val v2 = "beta" + + assertTrue(naturalOrder().compare(v1, v2) < 0) + assertTrue(reverseOrder().compare(v1, v2) > 0) + assertTrue(reverseOrder() === naturalOrder().reversed()) + assertTrue(naturalOrder() === reverseOrder().reversed()) + } + @Test fun sortByThenBy() { - val comparator = compareBy { it.rating } thenBy { it.name } + val comparator = compareBy { it.rating }.thenBy { it.name } val diff = comparator.compare(v1, v2) assertTrue(diff < 0) @@ -87,7 +106,7 @@ class OrderingTest { @Test fun sortByThenByDescending() { - val comparator = compareBy { it.rating } thenByDescending { it.name } + val comparator = compareBy { it.rating }.thenByDescending { it.name } val diff = comparator.compare(v1, v2) assertTrue(diff < 0)