Cleanup ordering, improve API

This commit is contained in:
Ilya Ryzhenkov
2014-11-07 17:07:35 +03:00
parent e890c2ee0d
commit 828ba385ea
13 changed files with 208 additions and 194 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ private val DEFAULT_LOAD_FACTOR = 0.75f
library
public trait Comparator<T> {
fun compare(obj1: T, obj2: T): Int;
public fun compare(obj1: T, obj2: T): Int;
}
library
-3
View File
@@ -2,9 +2,6 @@ package kotlin
import java.util.*
library("comparator")
public fun comparator<T>(f : (T, T) -> Int): Comparator<T> = noImpl
library
public fun <T> array(vararg value : T): Array<T> = noImpl
-23
View File
@@ -831,29 +831,6 @@
compare: throwAbstractFunctionInvocationError("Comparator#compare")
});
/**
* @class
* @implements {Kotlin.Comparator.<T>}
*
* @constructor
* @param {function(T,T): Boolean} comparator
* @template T
*/
var ComparatorImpl = Kotlin.createClassNow(Kotlin.Comparator,
function (comparator) {
this.compare = comparator;
}
);
/**
* @param {function(T,T): Boolean} f
* @returns {Kotlin.Comparator.<T>}
* @template T
*/
Kotlin.comparator = function (f) {
return new ComparatorImpl(f);
};
Kotlin.collectionsMax = function (c, comp) {
if (c.isEmpty()) {
//TODO: which exception?
+16 -17
View File
@@ -136,7 +136,7 @@ public fun <T> Iterable<T>.sortBy(comparator: Comparator<in T>): List<T> {
*/
public inline fun <T, R : Comparable<R>> Array<out T>.sortBy(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) order: (T) -> R): List<T> {
val sortedList = toArrayList()
val sortBy: Comparator<T> = comparator<T> {(x: T, y: T) -> order(x).compareTo(order(y)) }
val sortBy: Comparator<T> = compareBy(order)
java.util.Collections.sort(sortedList, sortBy)
return sortedList
}
@@ -146,7 +146,7 @@ public inline fun <T, R : Comparable<R>> Array<out T>.sortBy(inlineOptions(Inlin
*/
public inline fun <T, R : Comparable<R>> Iterable<T>.sortBy(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) order: (T) -> R): List<T> {
val sortedList = toArrayList()
val sortBy: Comparator<T> = comparator<T> {(x: T, y: T) -> order(x).compareTo(order(y)) }
val sortBy: Comparator<T> = compareBy(order)
java.util.Collections.sort(sortedList, sortBy)
return sortedList
}
@@ -156,8 +156,7 @@ public inline fun <T, R : Comparable<R>> Iterable<T>.sortBy(inlineOptions(Inline
*/
public fun <T : Comparable<T>> Iterable<T>.sortDescending(): List<T> {
val sortedList = toArrayList()
val sortBy: Comparator<T> = comparator<T> {(x: T, y: T) -> y.compareTo(x) }
java.util.Collections.sort(sortedList, sortBy)
java.util.Collections.sort(sortedList, comparator { x, y -> y.compareTo(x) })
return sortedList
}
@@ -166,7 +165,7 @@ public fun <T : Comparable<T>> Iterable<T>.sortDescending(): List<T> {
*/
public inline fun <T, R : Comparable<R>> Array<out T>.sortDescendingBy(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) order: (T) -> R): List<T> {
val sortedList = toArrayList()
val sortBy: Comparator<T> = comparator<T> {(x: T, y: T) -> order(y).compareTo(order(x)) }
val sortBy: Comparator<T> = compareByDescending(order)
java.util.Collections.sort(sortedList, sortBy)
return sortedList
}
@@ -176,7 +175,7 @@ public inline fun <T, R : Comparable<R>> Array<out T>.sortDescendingBy(inlineOpt
*/
public inline fun <T, R : Comparable<R>> Iterable<T>.sortDescendingBy(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) order: (T) -> R): List<T> {
val sortedList = toArrayList()
val sortBy: Comparator<T> = comparator<T> {(x: T, y: T) -> order(y).compareTo(order(x)) }
val sortBy: Comparator<T> = compareByDescending(order)
java.util.Collections.sort(sortedList, sortBy)
return sortedList
}
@@ -285,7 +284,7 @@ public fun <T : Comparable<T>> Stream<T>.toSortedList(): List<T> {
*/
public fun <T, V : Comparable<V>> Array<out T>.toSortedListBy(order: (T) -> V): List<T> {
val sortedList = toArrayList()
val sortBy: Comparator<T> = comparator<T> {(x: T, y: T) -> order(x).compareTo(order(y)) }
val sortBy: Comparator<T> = compareBy(order)
java.util.Collections.sort(sortedList, sortBy)
return sortedList
}
@@ -295,7 +294,7 @@ public fun <T, V : Comparable<V>> Array<out T>.toSortedListBy(order: (T) -> V):
*/
public fun <V : Comparable<V>> BooleanArray.toSortedListBy(order: (Boolean) -> V): List<Boolean> {
val sortedList = toArrayList()
val sortBy: Comparator<Boolean> = comparator<Boolean> {(x: Boolean, y: Boolean) -> order(x).compareTo(order(y)) }
val sortBy: Comparator<Boolean> = compareBy(order)
java.util.Collections.sort(sortedList, sortBy)
return sortedList
}
@@ -305,7 +304,7 @@ public fun <V : Comparable<V>> BooleanArray.toSortedListBy(order: (Boolean) -> V
*/
public fun <V : Comparable<V>> ByteArray.toSortedListBy(order: (Byte) -> V): List<Byte> {
val sortedList = toArrayList()
val sortBy: Comparator<Byte> = comparator<Byte> {(x: Byte, y: Byte) -> order(x).compareTo(order(y)) }
val sortBy: Comparator<Byte> = compareBy(order)
java.util.Collections.sort(sortedList, sortBy)
return sortedList
}
@@ -315,7 +314,7 @@ public fun <V : Comparable<V>> ByteArray.toSortedListBy(order: (Byte) -> V): Lis
*/
public fun <V : Comparable<V>> CharArray.toSortedListBy(order: (Char) -> V): List<Char> {
val sortedList = toArrayList()
val sortBy: Comparator<Char> = comparator<Char> {(x: Char, y: Char) -> order(x).compareTo(order(y)) }
val sortBy: Comparator<Char> = compareBy(order)
java.util.Collections.sort(sortedList, sortBy)
return sortedList
}
@@ -325,7 +324,7 @@ public fun <V : Comparable<V>> CharArray.toSortedListBy(order: (Char) -> V): Lis
*/
public fun <V : Comparable<V>> DoubleArray.toSortedListBy(order: (Double) -> V): List<Double> {
val sortedList = toArrayList()
val sortBy: Comparator<Double> = comparator<Double> {(x: Double, y: Double) -> order(x).compareTo(order(y)) }
val sortBy: Comparator<Double> = compareBy(order)
java.util.Collections.sort(sortedList, sortBy)
return sortedList
}
@@ -335,7 +334,7 @@ public fun <V : Comparable<V>> DoubleArray.toSortedListBy(order: (Double) -> V):
*/
public fun <V : Comparable<V>> FloatArray.toSortedListBy(order: (Float) -> V): List<Float> {
val sortedList = toArrayList()
val sortBy: Comparator<Float> = comparator<Float> {(x: Float, y: Float) -> order(x).compareTo(order(y)) }
val sortBy: Comparator<Float> = compareBy(order)
java.util.Collections.sort(sortedList, sortBy)
return sortedList
}
@@ -345,7 +344,7 @@ public fun <V : Comparable<V>> FloatArray.toSortedListBy(order: (Float) -> V): L
*/
public fun <V : Comparable<V>> IntArray.toSortedListBy(order: (Int) -> V): List<Int> {
val sortedList = toArrayList()
val sortBy: Comparator<Int> = comparator<Int> {(x: Int, y: Int) -> order(x).compareTo(order(y)) }
val sortBy: Comparator<Int> = compareBy(order)
java.util.Collections.sort(sortedList, sortBy)
return sortedList
}
@@ -355,7 +354,7 @@ public fun <V : Comparable<V>> IntArray.toSortedListBy(order: (Int) -> V): List<
*/
public fun <V : Comparable<V>> LongArray.toSortedListBy(order: (Long) -> V): List<Long> {
val sortedList = toArrayList()
val sortBy: Comparator<Long> = comparator<Long> {(x: Long, y: Long) -> order(x).compareTo(order(y)) }
val sortBy: Comparator<Long> = compareBy(order)
java.util.Collections.sort(sortedList, sortBy)
return sortedList
}
@@ -365,7 +364,7 @@ public fun <V : Comparable<V>> LongArray.toSortedListBy(order: (Long) -> V): Lis
*/
public fun <V : Comparable<V>> ShortArray.toSortedListBy(order: (Short) -> V): List<Short> {
val sortedList = toArrayList()
val sortBy: Comparator<Short> = comparator<Short> {(x: Short, y: Short) -> order(x).compareTo(order(y)) }
val sortBy: Comparator<Short> = compareBy(order)
java.util.Collections.sort(sortedList, sortBy)
return sortedList
}
@@ -375,7 +374,7 @@ public fun <V : Comparable<V>> ShortArray.toSortedListBy(order: (Short) -> V): L
*/
public fun <T, V : Comparable<V>> Iterable<T>.toSortedListBy(order: (T) -> V): List<T> {
val sortedList = toArrayList()
val sortBy: Comparator<T> = comparator<T> {(x: T, y: T) -> order(x).compareTo(order(y)) }
val sortBy: Comparator<T> = compareBy(order)
java.util.Collections.sort(sortedList, sortBy)
return sortedList
}
@@ -385,7 +384,7 @@ public fun <T, V : Comparable<V>> Iterable<T>.toSortedListBy(order: (T) -> V): L
*/
public fun <T, V : Comparable<V>> Stream<T>.toSortedListBy(order: (T) -> V): List<T> {
val sortedList = toArrayList()
val sortBy: Comparator<T> = comparator<T> {(x: T, y: T) -> order(x).compareTo(order(y)) }
val sortBy: Comparator<T> = compareBy(order)
java.util.Collections.sort(sortedList, sortBy)
return sortedList
}
+3 -1
View File
@@ -50,7 +50,6 @@ public fun <T> Iterable<T>.containsItem(item : T) : Boolean = contains(item)
deprecated("Use sortBy() instead")
public fun <T> Iterable<T>.sort(comparator: java.util.Comparator<T>) : List<T> = sortBy(comparator)
deprecated("Use size() instead")
public val Array<*>.size: Int get() = size()
@@ -77,3 +76,6 @@ public val DoubleArray.size: Int get() = size()
deprecated("Use size() instead")
public val BooleanArray.size: Int get() = size()
deprecated("Use compareValuesBy() instead")
public fun <T : Any> compareBy(a: T?, b: T?, vararg functions: (T) -> Comparable<*>?): Int = compareValuesBy(a, b, *functions)
+89 -10
View File
@@ -16,18 +16,19 @@
package kotlin
import java.util.Comparator
/**
* Helper method for implementing [[Comparable]] methods using a list of functions
* to calculate the values to compare
* Compares two values using the sequence of functions to calculate a result of comparison.
*/
public fun <T : Any> compareBy(a: T?, b: T?, vararg functions: T.() -> Comparable<*>?): Int {
public fun <T : Any> compareValuesBy(a: T?, b: T?, vararg functions: (T) -> Comparable<*>?): Int {
require(functions.size > 0)
if (a identityEquals b) return 0
if (a == null) return - 1
if (a == null) return -1
if (b == null) return 1
for (fn in functions) {
val v1 = a.fn()
val v2 = b.fn()
val v1 = fn(a)
val v2 = fn(b)
val diff = compareValues(v1, v2)
if (diff != 0) return diff
}
@@ -35,14 +36,92 @@ public fun <T : Any> compareBy(a: T?, b: T?, vararg functions: T.() -> Comparabl
}
/**
* Compares the two values which may be [[Comparable]] otherwise
* they are compared via [[#equals()]] and if they are not the same then
* the [[#hashCode()]] method is used as the difference
* Compares two [Comparable] nullable values, null is considered less than any value.
*/
public fun <T : Comparable<*>> compareValues(a: T?, b: T?): Int {
if (a identityEquals b) return 0
if (a == null) return - 1
if (a == null) return -1
if (b == null) return 1
return (a as Comparable<Any?>).compareTo(b)
}
/**
* Creates a comparator using the sequence of functions to calculate a result of comparison.
*/
public fun <T> compareBy(vararg functions: (T) -> Comparable<*>?): Comparator<T> {
return object : Comparator<T> {
public override fun compare(a: T, b: T): Int = compareValuesBy(a, b, *functions)
}
}
/**
* Creates a comparator using the sequence of functions to calculate a result of comparison.
*/
deprecated("Use compareBy() instead")
public fun <T> comparator(vararg functions: (T) -> Comparable<*>?): Comparator<T> = compareBy(*functions)
/**
* Creates a comparator using the function to transform value to a [Comparable] instance for comparison
*/
inline public fun <T> compareBy(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) comparable: (T) -> Comparable<*>): Comparator<T> {
return object : Comparator<T> {
public override fun compare(a: T, b: T): Int = compareValues(comparable(a), comparable(b))
}
}
/**
* Creates a descending comparator using the function to transform value to a [Comparable] instance for comparison
*/
inline public fun <T> compareByDescending(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) comparable: (T) -> Comparable<*>): Comparator<T> {
return object : Comparator<T> {
public override fun compare(a: T, b: T): Int = compareValues(comparable(b), comparable(a))
}
}
/**
* Creates a comparator using the primary comparator and
* the function to transform value to a [Comparable] instance for comparison
*/
inline public fun <T> Comparator<T>.thenBy(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) comparable: (T) -> Comparable<*>): Comparator<T> {
return object : Comparator<T> {
public override fun compare(a: T, b: T): Int {
val previousCompare = this@thenBy.compare(a, b)
return if (previousCompare != 0) previousCompare else compareValues(comparable(a), comparable(b))
}
}
}
/**
* Creates a descending comparator using the primary comparator and
* the function to transform value to a [Comparable] instance for comparison
*/
inline public fun <T> Comparator<T>.thenByDescending(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) comparable: (T) -> Comparable<*>): Comparator<T> {
return object : Comparator<T> {
public override fun compare(a: T, b: T): Int {
val previousCompare = this@thenByDescending.compare(a, b)
return if (previousCompare != 0) previousCompare else compareValues(comparable(b), comparable(a))
}
}
}
/**
* Creates a comparator using the function to calculate a result of comparison.
*/
inline public fun <T> comparator(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) comparison: (T, T) -> Int): Comparator<T> {
return object : Comparator<T> {
public override fun compare(a: T, b: T): Int = comparison(a, b)
}
}
/**
* Creates a comparator using the primary comparator and function to calculate a result of comparison.
*/
inline public fun <T> Comparator<T>.thenComparator(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) comparison: (T, T) -> Int): Comparator<T> {
return object : Comparator<T> {
public override fun compare(a: T, b: T): Int {
val previousCompare = this@thenComparator.compare(a, b)
return if (previousCompare != 0) previousCompare else comparison(a, b)
}
}
}
@@ -1,51 +0,0 @@
package kotlin
import java.util.Comparator
/**
* Creates a comparator using the sequence of functions used to calculate a value to compare on
*/
public fun <T> comparator(vararg functions: T.() -> Comparable<*>?): Comparator<T> {
return FunctionComparator<T>(*functions)
}
private class FunctionComparator<T>(private vararg val functions: T.() -> Comparable<*>?) : Comparator<T> {
public override fun toString(): String {
return "FunctionComparator${functions.toList()}"
}
public override fun compare(o1: T, o2: T): Int {
return compareBy<T>(o1, o2, *functions)
}
public override fun equals(obj: Any?): Boolean {
return this == obj
}
}
/**
* Creates a comparator using the sequence of functions used to calculate a value to compare on
*/
public fun <T> comparator(fn: (T,T) -> Int): Comparator<T> {
return Function2Comparator<T>(fn)
}
private class Function2Comparator<T>(private val compareFn: (T, T) -> Int) : Comparator<T> {
public override fun toString(): String {
return "Function2Comparator${compareFn}"
}
public override fun compare(a: T, b: T): Int {
if (a === b) return 0
if (a == null) return -1
if (b == null) return 1
return (compareFn)(a, b)
}
public override fun equals(obj: Any?): Boolean {
return this == obj
}
}
-40
View File
@@ -1,40 +0,0 @@
package test.compare
import java.util.Comparator
import kotlin.test.*
import org.junit.Test
class CompareJVMTest {
val v1 = Item("wine", 9)
val v2 = Item("beer", 10)
Test fun sortUsingComparatorHelperMethod() {
val c = comparator<Item>({ rating }, { name })
println("Created comparator $c")
val diff = c.compare(v1, v2)
assertTrue(diff < 0)
val items = arrayListOf(v1, v2)
items.sortBy(c)
println("Sorted list in rating order $items")
}
Test fun sortUsingCustomComparator() {
val c = object : Comparator<Item>{
override fun compare(o1: Item, o2: Item): Int {
return compareBy(o1, o2, { name }, { rating })
}
override fun equals(obj: Any?): Boolean {
return this == obj
}
}
println("Created comparator $c")
val diff = c.compare(v1, v2)
assertTrue(diff > 0)
val items = arrayListOf(v1, v2)
items.sortBy(c)
println("Sorted list in rating order $items")
}
}
-37
View File
@@ -1,37 +0,0 @@
package test.compare
import kotlin.test.*
import org.junit.Test
class Item(val name: String, val rating: Int): Comparable<Item> {
override fun toString() = "Item($name, $rating)"
public override fun compareTo(other: Item): Int {
return compareBy(this, other, { rating }, { name })
}
}
class CompareTest {
val v1 = Item("wine", 9)
val v2 = Item("beer", 10)
Test fun compareByCompareTo() {
val diff = v1.compareTo(v2)
assertTrue(diff < 0)
}
Test fun compareByNameFirst() {
val diff = compareBy(v1, v2, { name }, { rating })
assertTrue(diff > 0)
}
Test fun compareByRatingFirst() {
val diff = compareBy(v1, v2, { rating }, { name })
assertTrue(diff < 0)
}
Test fun compareSameObjectsByRatingFirst() {
val diff = compareBy(v1, v1, { rating }, { name })
assertTrue(diff == 0)
}
}
+93
View File
@@ -0,0 +1,93 @@
package test.compare
import java.util.*
import kotlin.test.*
import org.junit.Test
data class Item(val name: String, val rating: Int) : Comparable<Item> {
public override fun compareTo(other: Item): Int {
return compareValuesBy(this, other, { it.rating }, { it.name })
}
}
class OrderingTest {
val v1 = Item("wine", 9)
val v2 = Item("beer", 10)
Test fun compareByCompareTo() {
val diff = v1.compareTo(v2)
assertTrue(diff < 0)
}
Test fun compareByNameFirst() {
val diff = compareValuesBy(v1, v2, { it.name }, { it.rating })
assertTrue(diff > 0)
}
Test fun compareByRatingFirst() {
val diff = compareValuesBy(v1, v2, { it.rating }, { it.name })
assertTrue(diff < 0)
}
Test fun compareSameObjectsByRatingFirst() {
val diff = compareValuesBy(v1, v1, { it.rating }, { it.name })
assertTrue(diff == 0)
}
Test fun sortComparatorThenComparator() {
val comparator = comparator<Item> {(a, b) -> a.name.compareTo(b.name) } thenComparator {(a, b) -> a.rating.compareTo(b.rating) }
val diff = comparator.compare(v1, v2)
assertTrue(diff > 0)
val items = arrayListOf(v1, v2).sortBy(comparator)
assertEquals(v2, items[0])
assertEquals(v1, items[1])
}
Test fun sortByThenBy() {
val comparator = compareBy<Item> { it.rating } thenBy { it.name }
val diff = comparator.compare(v1, v2)
assertTrue(diff < 0)
val items = arrayListOf(v1, v2).sortBy(comparator)
assertEquals(v1, items[0])
assertEquals(v2, items[1])
}
Test fun sortByThenByDescending() {
val comparator = compareBy<Item> { it.rating } thenByDescending { it.name }
val diff = comparator.compare(v1, v2)
assertTrue(diff < 0)
val items = arrayListOf(v1, v2).sortBy(comparator)
assertEquals(v1, items[0])
assertEquals(v2, items[1])
}
Test fun sortUsingFunctionalComparator() {
val comparator = compareBy<Item>({ it.name }, { it.rating })
val diff = comparator.compare(v1, v2)
assertTrue(diff > 0)
val items = arrayListOf(v1, v2).sortBy(comparator)
assertEquals(v2, items[0])
assertEquals(v1, items[1])
}
Test fun sortUsingCustomComparator() {
val comparator = object : Comparator<Item> {
override fun compare(o1: Item, o2: Item): Int {
return compareValuesBy(o1, o2, { it.name }, { it.rating })
}
override fun equals(other: Any?): Boolean {
return this == other
}
}
val diff = comparator.compare(v1, v2)
assertTrue(diff > 0)
val items = arrayListOf(v1, v2).sortBy(comparator)
assertEquals(v2, items[0])
assertEquals(v1, items[1])
}
}
@@ -23,11 +23,7 @@ class MapJVMTest {
test fun toSortedMapWithComparator() {
val map = mapOf(Pair("c", 3), Pair("bc", 2), Pair("bd", 4), Pair("abc", 1))
val c = comparator<String>{ a, b ->
val answer = a.length() - b.length()
if (answer == 0) a.compareTo(b) else answer
}
val sorted = map.toSortedMap(c)
val sorted = map.toSortedMap(compareBy<String> { it.length() } thenBy { it })
assertEquals(arrayListOf("c", "bc", "bd", "abc"), sorted.keySet().toList())
assertEquals(1, sorted["abc"])
assertEquals(2, sorted["bc"])
@@ -114,7 +114,7 @@ class KDocConfig() {
private object LongestFirstStringComparator : Comparator<String> {
override fun compare(o1: String, o2: String): Int {
return compareBy<String>(o1, o2, { length() }, { this })
return compareValuesBy<String>(o1, o2, { it.length() }, { it })
}
override fun equals(other: Any?): Boolean {
@@ -80,8 +80,7 @@ fun ordering(): List<GenericFunction> {
body {
"""
val sortedList = toArrayList()
val sortBy: Comparator<T> = comparator<T> {(x: T, y: T) -> y.compareTo(x) }
java.util.Collections.sort(sortedList, sortBy)
java.util.Collections.sort(sortedList, comparator { x, y -> y.compareTo(x) })
return sortedList
"""
}
@@ -105,7 +104,7 @@ fun ordering(): List<GenericFunction> {
body {
"""
val sortedList = toArrayList()
val sortBy: Comparator<T> = comparator<T> {(x: T, y: T) -> order(x).compareTo(order(y)) }
val sortBy: Comparator<T> = compareBy(order)
java.util.Collections.sort(sortedList, sortBy)
return sortedList
"""
@@ -128,7 +127,7 @@ fun ordering(): List<GenericFunction> {
body {
"""
val sortedList = toArrayList()
val sortBy: Comparator<T> = comparator<T> {(x: T, y: T) -> order(x).compareTo(order(y)) }
val sortBy: Comparator<T> = compareBy(order)
java.util.Collections.sort(sortedList, sortBy)
return sortedList
"""
@@ -150,7 +149,7 @@ fun ordering(): List<GenericFunction> {
body {
"""
val sortedList = toArrayList()
val sortBy: Comparator<T> = comparator<T> {(x: T, y: T) -> order(y).compareTo(order(x)) }
val sortBy: Comparator<T> = compareByDescending(order)
java.util.Collections.sort(sortedList, sortBy)
return sortedList
"""