From 96e322c7d524e4fe663089308f6210a806f8c9ae Mon Sep 17 00:00:00 2001 From: scache Date: Mon, 9 Oct 2017 01:56:20 +0900 Subject: [PATCH] Add samples for Comparisons #KT-20357 --- .../test/samples/comparisons/comparisons.kt | 248 ++++++++++++++++++ .../src/kotlin/comparisons/Comparisons.kt | 50 +++- 2 files changed, 297 insertions(+), 1 deletion(-) create mode 100644 libraries/stdlib/samples/test/samples/comparisons/comparisons.kt diff --git a/libraries/stdlib/samples/test/samples/comparisons/comparisons.kt b/libraries/stdlib/samples/test/samples/comparisons/comparisons.kt new file mode 100644 index 00000000000..338f1a5f285 --- /dev/null +++ b/libraries/stdlib/samples/test/samples/comparisons/comparisons.kt @@ -0,0 +1,248 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package samples.comparisons + +import samples.* +import kotlin.test.* + +class Comparisons { + @Sample + fun compareValuesByWithSingleSelector() { + fun compareLength(a: String, b: String): Int = + compareValuesBy(a, b) { it.length } + + assertTrue(compareLength("a", "b") == 0) + assertTrue(compareLength("bb", "a") > 0) + assertTrue(compareLength("a", "bb") < 0) + } + + @Sample + fun compareValuesByWithSelectors() { + fun compareLengthThenString(a: String, b: String): Int = + compareValuesBy(a, b, { it.length }, { it }) + + assertTrue(compareLengthThenString("b", "aa") < 0) + + assertTrue(compareLengthThenString("a", "b") < 0) + assertTrue(compareLengthThenString("b", "a") > 0) + assertTrue(compareLengthThenString("a", "a") == 0) + } + + @Sample + fun compareValuesByWithComparator() { + fun compareInsensitiveOrder(a: Char, b: Char): Int = + compareValuesBy(a, b, String.CASE_INSENSITIVE_ORDER, { c -> c.toString() }) + + assertTrue(compareInsensitiveOrder('a', 'a') == 0) + assertTrue(compareInsensitiveOrder('a', 'A') == 0) + + assertTrue(compareInsensitiveOrder('a', 'b') < 0) + assertTrue(compareInsensitiveOrder('A', 'b') < 0) + assertTrue(compareInsensitiveOrder('b', 'a') > 0) + } + + @Sample + fun compareValues() { + assertTrue(compareValues(null, 1) < 0) + assertTrue(compareValues(1, 2) < 0) + assertTrue(compareValues(2, 1) > 0) + assertTrue(compareValues(1, 1) == 0) + } + + @Sample + fun compareByWithSingleSelector() { + val list = listOf("aa", "b", "bb", "a") + + val sorted = list.sortedWith(compareBy { it.length }) + + assertPrints(sorted, "[b, a, aa, bb]") + } + + @Sample + fun compareByWithSelectors() { + val list = listOf("aa", "b", "bb", "a") + + val sorted = list.sortedWith(compareBy( + { it.length }, + { it } + )) + + assertPrints(sorted, "[a, b, aa, bb]") + } + + @Sample + fun compareByWithComparator() { + val list = listOf('B', 'a', 'A', 'b') + + val sorted = list.sortedWith( + compareBy(String.CASE_INSENSITIVE_ORDER) { v -> v.toString() } + ) + + assertPrints(sorted, "[a, A, B, b]") + } + + @Sample + fun compareByDescendingWithSingleSelector() { + val list = listOf("aa", "b", "bb", "a") + + val sorted = list.sortedWith(compareByDescending { it.length }) + + assertPrints(sorted, "[aa, bb, b, a]") + } + + @Sample + fun compareByDescendingWithComparator() { + val list = listOf('B', 'a', 'A', 'b') + + val sorted = list.sortedWith( + compareByDescending(String.CASE_INSENSITIVE_ORDER) { v -> v.toString() } + ) + + assertPrints(sorted, "[B, b, a, A]") + } + + @Sample + fun thenBy() { + val list = listOf("aa", "b", "bb", "a") + + val lengthComparator = compareBy { it.length } + assertPrints(list.sortedWith(lengthComparator), "[b, a, aa, bb]") + + val lengthThenString = lengthComparator.thenBy { it } + assertPrints(list.sortedWith(lengthThenString), "[a, b, aa, bb]") + } + + @Sample + fun thenByWithComparator() { + val list = listOf("A", "aa", "b", "bb", "a") + + val lengthComparator = compareBy { it.length } + assertPrints(list.sortedWith(lengthComparator), "[A, b, a, aa, bb]") + + val lengthThenCaseInsensitive = lengthComparator + .thenBy(String.CASE_INSENSITIVE_ORDER) { it } + assertPrints(list.sortedWith(lengthThenCaseInsensitive), "[A, a, b, aa, bb]") + } + + @Sample + fun thenByDescending() { + val list = listOf("aa", "b", "bb", "a") + + val lengthComparator = compareBy { it.length } + assertPrints(list.sortedWith(lengthComparator), "[b, a, aa, bb]") + + val lengthThenStringDesc = lengthComparator.thenByDescending { it } + assertPrints(list.sortedWith(lengthThenStringDesc), "[b, a, bb, aa]") + } + + @Sample + fun thenByDescendingWithComparator() { + val list = listOf("A", "aa", "b", "bb", "a") + + val lengthComparator = compareBy { it.length } + assertPrints(list.sortedWith(lengthComparator), "[A, b, a, aa, bb]") + + val lengthThenCaseInsensitive = lengthComparator + .thenByDescending(String.CASE_INSENSITIVE_ORDER) { it } + assertPrints(list.sortedWith(lengthThenCaseInsensitive), "[b, A, a, bb, aa]") + } + + @Sample + fun thenComparator() { + val array = arrayOf("c" to 1, "b" to 2, "a" to 1, "d" to 0, null to 0) + + val valueComparator = compareBy> { it.second } + val map1 = listOf(*array).sortedWith(valueComparator).toMap() + assertPrints(map1, "{d=0, null=0, c=1, a=1, b=2}") + + val valueThenKeyComparator = valueComparator + .thenComparator({ a, b -> compareValues(a.first, b.first) }) + val map2 = listOf(*array).sortedWith(valueThenKeyComparator).toMap() + assertPrints(map2, "{null=0, d=0, a=1, c=1, b=2}") + } + + @Sample + fun then() { + val list = listOf("A", "aa", "b", "bb", "a") + + val lengthThenCaseInsensitive = compareBy { it.length } + .then(String.CASE_INSENSITIVE_ORDER) + + val sorted = list.sortedWith(lengthThenCaseInsensitive) + + assertPrints(sorted, "[A, a, b, aa, bb]") + } + + @Sample + fun thenDescending() { + val list = listOf("A", "aa", "b", "bb", "a") + + val lengthThenCaseInsensitive = compareBy { it.length } + .thenDescending(String.CASE_INSENSITIVE_ORDER) + + val sorted = list.sortedWith(lengthThenCaseInsensitive) + + assertPrints(sorted, "[b, A, a, bb, aa]") + } + + @Sample + fun nullsFirstLastComparator() { + val list = listOf(4, null, -1, 1) + + val nullsFirstList = list.sortedWith(nullsFirst()) + assertPrints(nullsFirstList, "[null, -1, 1, 4]") + + val nullsLastList = list.sortedWith(nullsLast()) + assertPrints(nullsLastList, "[-1, 1, 4, null]") + } + + @Sample + fun nullsFirstLastWithComparator() { + val list = listOf(4, null, 1, -2, 3) + + val nullsFirstList = list.sortedWith(nullsFirst(reverseOrder())) + assertPrints(nullsFirstList, "[null, 4, 3, 1, -2]") + + val nullsLastList = list.sortedWith(nullsLast(reverseOrder())) + assertPrints(nullsLastList, "[4, 3, 1, -2, null]") + } + + @Sample + fun naturalOrderComparator() { + val list = listOf("aa", "b", "bb", "a") + + val lengthThenNatural = compareBy { it.length } + .then(naturalOrder()) + + val sorted = list.sortedWith(lengthThenNatural) + + assertPrints(sorted, "[a, b, aa, bb]") + } + + @Sample + fun reversed() { + val list = listOf("aa", "b", "bb", "a") + + val lengthThenString = compareBy { it.length }.thenBy { it } + + val sorted = list.sortedWith(lengthThenString) + assertPrints(sorted, "[a, b, aa, bb]") + + val sortedReversed = list.sortedWith(lengthThenString.reversed()) + assertPrints(sortedReversed, "[bb, aa, b, a]") + } +} \ No newline at end of file diff --git a/libraries/stdlib/src/kotlin/comparisons/Comparisons.kt b/libraries/stdlib/src/kotlin/comparisons/Comparisons.kt index e75996aae31..191ff0513e2 100644 --- a/libraries/stdlib/src/kotlin/comparisons/Comparisons.kt +++ b/libraries/stdlib/src/kotlin/comparisons/Comparisons.kt @@ -23,6 +23,8 @@ package kotlin.comparisons * The functions are called sequentially, receive the given values [a] and [b] and return [Comparable] * objects. As soon as the [Comparable] instances returned by a function for [a] and [b] values do not * compare as equal, the result of that comparison is returned. + * + * @sample samples.comparisons.Comparisons.compareValuesByWithSelectors */ public fun compareValuesBy(a: T, b: T, vararg selectors: (T) -> Comparable<*>?): Int { require(selectors.size > 0) @@ -43,6 +45,8 @@ private fun compareValuesByImpl(a: T, b: T, selectors: ArrayCompar * Compares two values using the specified [selector] function to calculate the result of the comparison. * The function is applied to the given values [a] and [b] and return [Comparable] objects. * The result of comparison of these [Comparable] instances is returned. + * + * @sample samples.comparisons.Comparisons.compareValuesByWithSingleSelector */ @kotlin.internal.InlineOnly public inline fun compareValuesBy(a: T, b: T, selector: (T) -> Comparable<*>?): Int { @@ -53,6 +57,8 @@ public inline fun compareValuesBy(a: T, b: T, selector: (T) -> Comparable<*> * Compares two values using the specified [selector] function to calculate the result of the comparison. * The function is applied to the given values [a] and [b] and return objects of type K which are then being * compared with the given [comparator]. + * + * @sample samples.comparisons.Comparisons.compareValuesByWithComparator */ @kotlin.internal.InlineOnly public inline fun compareValuesBy(a: T, b: T, comparator: Comparator, selector: (T) -> K): Int { @@ -71,6 +77,8 @@ public inline fun compareValuesBy(a: T, b: T, comparator: Comparator> compareValues(a: T?, b: T?): Int { if (a === b) return 0 @@ -86,6 +94,8 @@ public fun > compareValues(a: T?, b: T?): Int { * The functions are called sequentially, receive the given values `a` and `b` and return [Comparable] * objects. As soon as the [Comparable] instances returned by a function for `a` and `b` values do not * compare as equal, the result of that comparison is returned from the [Comparator]. + * + * @sample samples.comparisons.Comparisons.compareByWithSelectors */ public fun compareBy(vararg selectors: (T) -> Comparable<*>?): Comparator { require(selectors.size > 0) @@ -96,6 +106,8 @@ public fun compareBy(vararg selectors: (T) -> Comparable<*>?): Comparator /** * Creates a comparator using the function to transform value to a [Comparable] instance for comparison. + * + * @sample samples.comparisons.Comparisons.compareByWithSingleSelector */ @kotlin.internal.InlineOnly public inline fun compareBy(crossinline selector: (T) -> Comparable<*>?): Comparator = @@ -104,6 +116,8 @@ public inline fun compareBy(crossinline selector: (T) -> Comparable<*>?): Co /** * Creates a comparator using the [selector] function to transform values being compared and then applying * the specified [comparator] to compare transformed values. + * + * @sample samples.comparisons.Comparisons.compareByWithComparator */ @kotlin.internal.InlineOnly public inline fun compareBy(comparator: Comparator, crossinline selector: (T) -> K): Comparator = @@ -111,6 +125,8 @@ public inline fun compareBy(comparator: Comparator, crossinline sel /** * Creates a descending comparator using the function to transform value to a [Comparable] instance for comparison. + * + * @sample samples.comparisons.Comparisons.compareByDescendingWithSingleSelector */ @kotlin.internal.InlineOnly public inline fun compareByDescending(crossinline selector: (T) -> Comparable<*>?): Comparator = @@ -121,6 +137,8 @@ public inline fun compareByDescending(crossinline selector: (T) -> Comparabl * the specified [comparator] to compare transformed values. * * Note that an order of [comparator] is reversed by this wrapper. + * + * @sample samples.comparisons.Comparisons.compareByDescendingWithComparator */ @kotlin.internal.InlineOnly public inline fun compareByDescending(comparator: Comparator, crossinline selector: (T) -> K): Comparator = @@ -129,6 +147,8 @@ public inline fun compareByDescending(comparator: Comparator, cross /** * Creates a comparator comparing values after the primary comparator defined them equal. It uses * the function to transform value to a [Comparable] instance for comparison. + * + * @sample samples.comparisons.Comparisons.thenBy */ @kotlin.internal.InlineOnly public inline fun Comparator.thenBy(crossinline selector: (T) -> Comparable<*>?): Comparator = @@ -140,6 +160,8 @@ public inline fun Comparator.thenBy(crossinline selector: (T) -> Comparab /** * Creates a comparator comparing values after the primary comparator defined them equal. It uses * the [selector] function to transform values and then compares them with the given [comparator]. + * + * @sample samples.comparisons.Comparisons.thenByWithComparator */ @kotlin.internal.InlineOnly public inline fun Comparator.thenBy(comparator: Comparator, crossinline selector: (T) -> K): Comparator = @@ -151,6 +173,8 @@ public inline fun Comparator.thenBy(comparator: Comparator, cros /** * Creates a descending comparator using the primary comparator and * the function to transform value to a [Comparable] instance for comparison. + * + * @sample samples.comparisons.Comparisons.thenByDescending */ @kotlin.internal.InlineOnly public inline fun Comparator.thenByDescending(crossinline selector: (T) -> Comparable<*>?): Comparator = @@ -162,6 +186,8 @@ public inline fun Comparator.thenByDescending(crossinline selector: (T) - /** * Creates a descending comparator comparing values after the primary comparator defined them equal. It uses * the [selector] function to transform values and then compares them with the given [comparator]. + * + * @sample samples.comparisons.Comparisons.thenByDescendingWithComparator */ @kotlin.internal.InlineOnly public inline fun Comparator.thenByDescending(comparator: Comparator, crossinline selector: (T) -> K): Comparator = @@ -173,6 +199,8 @@ public inline fun Comparator.thenByDescending(comparator: Comparator Comparator.thenComparator(crossinline comparison: (a: T, b: T) -> Int): Comparator = @@ -184,6 +212,8 @@ public inline fun Comparator.thenComparator(crossinline comparison: (a: T /** * Combines this comparator and the given [comparator] such that the latter is applied only * when the former considered values equal. + * + * @sample samples.comparisons.Comparisons.then */ public infix fun Comparator.then(comparator: Comparator): Comparator = Comparator { a, b -> @@ -194,6 +224,8 @@ public infix fun Comparator.then(comparator: Comparator): Comparato /** * Combines this comparator and the given [comparator] such that the latter is applied only * when the former considered values equal. + * + * @sample samples.comparisons.Comparisons.thenDescending */ public infix fun Comparator.thenDescending(comparator: Comparator): Comparator = Comparator { a, b -> @@ -205,6 +237,8 @@ public infix fun Comparator.thenDescending(comparator: Comparator): /** * Extends the given [comparator] of non-nullable values to a comparator of nullable values * considering `null` value less than any other value. + * + * @sample samples.comparisons.Comparisons.nullsFirstLastWithComparator */ public fun nullsFirst(comparator: Comparator): Comparator = Comparator { a, b -> @@ -219,6 +253,8 @@ public fun nullsFirst(comparator: Comparator): Comparator = /** * Provides a comparator of nullable [Comparable] values * considering `null` value less than any other value. + * + * @sample samples.comparisons.Comparisons.nullsFirstLastComparator */ @kotlin.internal.InlineOnly public inline fun > nullsFirst(): Comparator = nullsFirst(naturalOrder()) @@ -226,6 +262,8 @@ public inline fun > nullsFirst(): Comparator = nullsFirst(n /** * Extends the given [comparator] of non-nullable values to a comparator of nullable values * considering `null` value greater than any other value. + * + * @sample samples.comparisons.Comparisons.nullsFirstLastWithComparator */ public fun nullsLast(comparator: Comparator): Comparator = Comparator { a, b -> @@ -240,21 +278,31 @@ public fun nullsLast(comparator: Comparator): Comparator = /** * Provides a comparator of nullable [Comparable] values * considering `null` value greater than any other value. + * + * @sample samples.comparisons.Comparisons.nullsFirstLastComparator */ @kotlin.internal.InlineOnly public inline fun > nullsLast(): Comparator = nullsLast(naturalOrder()) /** * Returns a comparator that compares [Comparable] objects in natural order. + * + * @sample samples.comparisons.Comparisons.naturalOrderComparator */ public fun > naturalOrder(): Comparator = @Suppress("UNCHECKED_CAST") (NaturalOrderComparator as Comparator) /** * Returns a comparator that compares [Comparable] objects in reversed natural order. + * + * @sample samples.comparisons.Comparisons.nullsFirstLastWithComparator */ public fun > reverseOrder(): Comparator = @Suppress("UNCHECKED_CAST") (ReverseOrderComparator as Comparator) -/** Returns a comparator that imposes the reverse ordering of this comparator. */ +/** + * Returns a comparator that imposes the reverse ordering of this comparator. + * + * @sample samples.comparisons.Comparisons.reversed + */ public fun Comparator.reversed(): Comparator = when (this) { is ReversedComparator -> this.comparator NaturalOrderComparator -> @Suppress("UNCHECKED_CAST") (ReverseOrderComparator as Comparator)