Sort collections/map APIs, improve empty implementations.

This commit is contained in:
Ilya Ryzhenkov
2014-12-01 16:26:39 +03:00
parent fa0542b801
commit 31fb24d390
13 changed files with 156 additions and 111 deletions
@@ -2,8 +2,8 @@ class A {}
fun <T> foo(t: T) {}
fun <T> emptyList(): List<T> = throw Exception()
fun <T> someList(): List<T> = throw Exception()
fun bar() {
<caret>foo(emptyList())
<caret>foo(someList())
}
@@ -2,10 +2,10 @@ class A {}
fun <T> foo(t: T) {}
fun <T> emptyList(): List<T> = throw Exception()
fun <T> someList(): List<T> = throw Exception()
fun bar() {
<caret>foo(emptyList())
<caret>foo(someList())
}
@@ -20,4 +20,4 @@ Extension receiver = NO_RECEIVER
Value arguments mapping:
MATCH_MODULO_UNINFERRED_TYPES t : List<???> = emptyList()
MATCH_MODULO_UNINFERRED_TYPES t : List<???> = someList()
@@ -2,8 +2,8 @@ class A {}
fun <T> foo(t: T) {}
fun <T> emptyList(): MutableList<T> = throw Exception()
fun <T> someList(): MutableList<T> = throw Exception()
fun bar() {
<caret>foo(emptyList())
<caret>foo(someList())
}
@@ -2,10 +2,10 @@ class A {}
fun <T> foo(t: T) {}
fun <T> emptyList(): MutableList<T> = throw Exception()
fun <T> someList(): MutableList<T> = throw Exception()
fun bar() {
<caret>foo(emptyList())
<caret>foo(someList())
}
@@ -20,4 +20,4 @@ Extension receiver = NO_RECEIVER
Value arguments mapping:
MATCH_MODULO_UNINFERRED_TYPES t : MutableList<???> = emptyList()
MATCH_MODULO_UNINFERRED_TYPES t : MutableList<???> = someList()
@@ -1,8 +1,8 @@
fun <T> emptyList(): List<T> = throw Exception()
fun <T> someList(): List<T> = throw Exception()
fun <T> doSmth(l: List<T>) {}
fun doSmth(a: Any) {}
fun bar() {
<caret>doSmth(emptyList())
<caret>doSmth(someList())
}
@@ -1,10 +1,10 @@
fun <T> emptyList(): List<T> = throw Exception()
fun <T> someList(): List<T> = throw Exception()
fun <T> doSmth(l: List<T>) {}
fun doSmth(a: Any) {}
fun bar() {
<caret>doSmth(emptyList())
<caret>doSmth(someList())
}
@@ -19,4 +19,4 @@ Extension receiver = NO_RECEIVER
Value arguments mapping:
MATCH_MODULO_UNINFERRED_TYPES l : List<???> = emptyList()
MATCH_MODULO_UNINFERRED_TYPES l : List<???> = someList()
@@ -1,5 +1,5 @@
// ERROR: Too many arguments for public fun <T> listOf(): kotlin.List<T> defined in kotlin
// ERROR: Null can not be a value of a non-null type kotlin.String
// ERROR: Too many arguments for public fun <T> setOf(): kotlin.Set<T> defined in kotlin
import java.util.*
class A {
@@ -144,3 +144,8 @@ public val Map<*, *>.size: Int
deprecated("Use isEmpty() function call instead")
public val Map<*, *>.empty: Boolean
get() = isEmpty()
/** Returns true if this collection is not empty */
deprecated("Use isNotEmpty() function call instead")
public val Collection<*>.notEmpty: Boolean
get() = isNotEmpty()
@@ -2,28 +2,52 @@ package kotlin
import java.util.*
private class stdlib_emptyListClass : List<Any> by ArrayList<Any>() {}
private val stdlib_emptyList : List<Any> = stdlib_emptyListClass()
private fun stdlib_emptyList<T>() = stdlib_emptyList as List<T>
private object EmptyList : List<Any> {
private val list = ArrayList<Any>()
private class stdlib_emptyMapClass : Map<Any, Any> by HashMap<Any, Any>() {}
private val stdlib_emptyMap : Map<Any, Any> = stdlib_emptyMapClass()
private fun stdlib_emptyMap<K,V>() = stdlib_emptyMap as Map<K,V>
override fun contains(o: Any?): Boolean = list.contains(o)
override fun containsAll(c: Collection<Any?>): Boolean = list.containsAll(c)
override fun get(index: Int): Any = list.get(index)
override fun indexOf(o: Any?): Int = list.indexOf(o)
override fun isEmpty(): Boolean = list.isEmpty()
override fun iterator(): Iterator<Any> = list.iterator()
override fun lastIndexOf(o: Any?): Int = list.lastIndexOf(o)
override fun listIterator(): ListIterator<Any> = list.listIterator()
override fun listIterator(index: Int): ListIterator<Any> =list.listIterator(index)
override fun size(): Int = list.size()
override fun subList(fromIndex: Int, toIndex: Int): List<Any> = list.subList(fromIndex, toIndex)
override fun equals(other: Any?): Boolean = list.equals(other)
override fun hashCode(): Int = list.hashCode()
override fun toString(): String = list.toString()
}
private object EmptySet : Set<Any> {
private val set = HashSet<Any>()
override fun contains(o: Any?): Boolean = set.contains(o)
override fun containsAll(c: Collection<Any?>): Boolean = set.containsAll(c)
override fun isEmpty(): Boolean = set.isEmpty()
override fun iterator(): Iterator<Any> = set.iterator()
override fun size(): Int = set.size()
override fun equals(other: Any?): Boolean = set.equals(other)
override fun hashCode(): Int = set.hashCode()
override fun toString(): String = set.toString()
}
public fun emptyList<T>(): List<T> = EmptyList as List<T>
public fun emptySet<T>(): Set<T> = EmptySet as Set<T>
/** Returns a new read-only list of given elements */
public fun listOf<T>(vararg values: T): List<T> = if (values.size() == 0) stdlib_emptyList() else arrayListOf(*values)
public fun listOf<T>(vararg values: T): List<T> = if (values.size() == 0) emptyList() else arrayListOf(*values)
/** Returns an empty list */
public fun listOf<T>(): List<T> = stdlib_emptyList()
/** Returns an empty read-only list */
public fun listOf<T>(): List<T> = emptyList()
/** Returns a new read-only map of given pairs, where the first value is the key, and the second is value */
public fun mapOf<K, V>(vararg values: Pair<K, V>): Map<K, V> = if (values.size() == 0) stdlib_emptyMap() else linkedMapOf(*values)
/** Returns a new read-only ordered set of given elements */
public fun setOf<T>(vararg values: T): Set<T> = if (values.size() == 0) emptySet() else values.toCollection(LinkedHashSet<T>())
/** Returns an empty read-only map */
public fun mapOf<K, V>(): Map<K, V> = stdlib_emptyMap()
/** Returns a new read-only set of given elements */
public fun setOf<T>(vararg values: T): Set<T> = values.toCollection(LinkedHashSet<T>())
/** Returns an empty read-only set */
public fun setOf<T>(): Set<T> = emptySet()
/** Returns a new LinkedList with a variable number of initial elements */
public fun linkedListOf<T>(vararg values: T): LinkedList<T> = values.toCollection(LinkedList<T>())
@@ -34,30 +58,8 @@ public fun arrayListOf<T>(vararg values: T): ArrayList<T> = values.toCollection(
/** Returns a new HashSet with a variable number of initial elements */
public fun hashSetOf<T>(vararg values: T): HashSet<T> = values.toCollection(HashSet(values.size()))
/**
* Returns a new [[HashMap]] populated with the given pairs where the first value in each pair
* is the key and the second value is the value
*
* @includeFunctionBody ../../test/collections/MapTest.kt createUsingPairs
*/
public fun <K, V> hashMapOf(vararg values: Pair<K, V>): HashMap<K, V> {
val answer = HashMap<K, V>(values.size())
answer.putAll(*values)
return answer
}
/**
* Returns a new [[LinkedHashMap]] populated with the given pairs where the first value in each pair
* is the key and the second value is the value. This map preserves insertion order so iterating through
* the map's entries will be in the same order
*
* @includeFunctionBody ../../test/collections/MapTest.kt createLinkedMap
*/
public fun <K, V> linkedMapOf(vararg values: Pair<K, V>): LinkedHashMap<K, V> {
val answer = LinkedHashMap<K, V>(values.size())
answer.putAll(*values)
return answer
}
/** Returns a new LinkedHashSet with a variable number of initial elements */
public fun linkedSetOf<T>(vararg values: T): HashSet<T> = values.toCollection(LinkedHashSet(values.size()))
public val Collection<*>.indices: IntRange
get() = 0..size() - 1
@@ -73,18 +75,14 @@ public val Int.indices: IntRange
public val <T> List<T>.lastIndex: Int
get() = this.size() - 1
/** Returns true if the collection is not empty */
public fun <T> Collection<T>.isNotEmpty(): Boolean = !this.isEmpty()
/** Returns true if this collection is not empty */
public val Collection<*>.notEmpty: Boolean
get() = isNotEmpty()
public fun <T> Collection<T>.isNotEmpty(): Boolean = !isEmpty()
/** Returns the Collection if its not null otherwise it returns the empty list */
public fun <T> Collection<T>?.orEmpty(): Collection<T> = this ?: stdlib_emptyList()
// List APIs
public fun <T> Collection<T>?.orEmpty(): Collection<T> = this ?: emptyList()
/** Returns the List if its not null otherwise returns the empty list */
public fun <T> List<T>?.orEmpty(): List<T> = this ?: stdlib_emptyList()
public fun <T> List<T>?.orEmpty(): List<T> = this ?: emptyList()
/** Returns the List if its not null otherwise returns the empty list */
public fun <T> Set<T>?.orEmpty(): Set<T> = this ?: emptySet()
@@ -12,29 +12,6 @@ public fun sortedSetOf<T>(vararg values: T): TreeSet<T> = values.toCollection(Tr
*/
public fun sortedSetOf<T>(comparator: Comparator<T>, vararg values: T): TreeSet<T> = values.toCollection(TreeSet<T>(comparator))
/**
* Returns a new [[SortedMap]] populated with the given pairs where the first value in each pair
* is the key and the second value is the value
*
* @includeFunctionBody ../../test/collections/MapTest.kt createSortedMap
*/
public fun <K, V> sortedMapOf(vararg values: Pair<K, V>): SortedMap<K, V> {
val answer = TreeMap<K, V>()
/**
TODO replace by this simpler call when we can pass vararg values into other methods
answer.putAll(values)
*/
for (v in values) {
answer.put(v.first, v.second)
}
return answer
}
/** Returns the Set if its not null otherwise returns the empty set */
public fun <T> Set<T>?.orEmpty(): Set<T>
= if (this != null) this else Collections.EMPTY_SET as Set<T>
/**
* Returns a list containing the elements returned by the
* specified enumeration in the order they are returned by the
+63 -10
View File
@@ -2,11 +2,59 @@ package kotlin
import java.util.*
// Map APIs
private object EmptyMap : Map<Any, Any> {
private val map = HashMap<Any, Any>()
override fun containsKey(key: Any?): Boolean = map.containsKey(key)
override fun containsValue(value: Any?): Boolean = map.containsValue(value)
override fun entrySet(): Set<Map.Entry<Any, Any>> = map.entrySet()
override fun get(key: Any?): Any? = map.get(key)
override fun keySet(): Set<Any> = map.keySet()
override fun values(): Collection<Any> = map.values()
override fun isEmpty(): Boolean = map.isEmpty()
override fun size(): Int = map.size()
override fun equals(other: Any?): Boolean = map.equals(other)
override fun hashCode(): Int = map.hashCode()
override fun toString(): String = map.toString()
}
/** Returns an empty read-only map of specified type */
public fun emptyMap<K, V>(): Map<K, V> = EmptyMap as Map<K, V>
/** Returns a new read-only map of given pairs, where the first value is the key, and the second is value */
public fun mapOf<K, V>(vararg values: Pair<K, V>): Map<K, V> = if (values.size() == 0) emptyMap() else linkedMapOf(*values)
/** Returns an empty read-only map */
public fun mapOf<K, V>(): Map<K, V> = emptyMap()
/**
* Returns a new [[HashMap]] populated with the given pairs where the first value in each pair
* is the key and the second value is the value
*
* @includeFunctionBody ../../test/collections/MapTest.kt createUsingPairs
*/
public fun <K, V> hashMapOf(vararg values: Pair<K, V>): HashMap<K, V> {
val answer = HashMap<K, V>(values.size())
answer.putAll(*values)
return answer
}
/**
* Returns a new [[LinkedHashMap]] populated with the given pairs where the first value in each pair
* is the key and the second value is the value. This map preserves insertion order so iterating through
* the map's entries will be in the same order
*
* @includeFunctionBody ../../test/collections/MapTest.kt createLinkedMap
*/
public fun <K, V> linkedMapOf(vararg values: Pair<K, V>): LinkedHashMap<K, V> {
val answer = LinkedHashMap<K, V>(values.size())
answer.putAll(*values)
return answer
}
/** Returns the [[Map]] if its not null otherwise it returns the empty [[Map]] */
public fun <K,V> Map<K,V>?.orEmpty() : Map<K,V>
= if (this != null) this else stdlib_emptyMap()
= if (this != null) this else emptyMap()
public fun <K,V> Map<K,V>.contains(key : K) : Boolean = containsKey(key)
@@ -39,8 +87,8 @@ public fun <K, V> Map.Entry<K, V>.toPair(): Pair<K, V> {
* @includeFunctionBody ../../test/collections/MapTest.kt getOrElse
*/
public inline fun <K, V> Map<K, V>.getOrElse(key: K, defaultValue: () -> V): V {
if (this.containsKey(key)) {
return this.get(key) as V
if (containsKey(key)) {
return get(key) as V
} else {
return defaultValue()
}
@@ -52,11 +100,11 @@ public inline fun <K, V> Map<K, V>.getOrElse(key: K, defaultValue: () -> V): V {
* @includeFunctionBody ../../test/collections/MapTest.kt getOrPut
*/
public inline fun <K, V> MutableMap<K, V>.getOrPut(key: K, defaultValue: () -> V): V {
if (this.containsKey(key)) {
return this.get(key) as V
if (containsKey(key)) {
return get(key) as V
} else {
val answer = defaultValue()
this.put(key, answer)
put(key, answer)
return answer
}
}
@@ -67,7 +115,7 @@ public inline fun <K, V> MutableMap<K, V>.getOrPut(key: K, defaultValue: () -> V
* @includeFunctionBody ../../test/collections/MapTest.kt iterateWithProperties
*/
public fun <K, V> Map<K, V>.iterator(): Iterator<Map.Entry<K, V>> {
val entrySet = this.entrySet()
val entrySet = entrySet()
return entrySet.iterator()
}
@@ -117,7 +165,7 @@ public fun <K, V> MutableMap<K, V>.putAll(values: Iterable<Pair<K,V>>): Unit {
* @includeFunctionBody ../../test/collections/MapTest.kt mapValues
*/
public inline fun <K, V, R> Map<K, V>.mapValues(transform: (Map.Entry<K, V>) -> R): Map<K, R> {
return mapValuesTo(LinkedHashMap<K, R>(this.size), transform)
return mapValuesTo(LinkedHashMap<K, R>(size()), transform)
}
/**
@@ -126,7 +174,7 @@ public inline fun <K, V, R> Map<K, V>.mapValues(transform: (Map.Entry<K, V>) ->
* @includeFunctionBody ../../test/collections/MapTest.kt mapKeys
*/
public inline fun <K, V, R> Map<K, V>.mapKeys(transform: (Map.Entry<K, V>) -> R): Map<R, V> {
return mapKeysTo(LinkedHashMap<R, V>(this.size), transform)
return mapKeysTo(LinkedHashMap<R, V>(size()), transform)
}
/**
@@ -211,3 +259,8 @@ public fun <K, V> Iterable<Pair<K, V>>.toMap(): Map<K, V> {
}
return result
}
/**
* Converts this [Map] to a [LinkedHashMap] so future insertion orders are maintained
*/
public fun <K, V> Map<K, V>.toLinkedMap(): MutableMap<K, V> = LinkedHashMap(this)
@@ -6,16 +6,9 @@ import java.util.SortedMap
import java.util.TreeMap
import java.util.Properties
// Map APIs
// Move back to Maps.kt after KT-2093 will be fixed
/** Provides [] access to maps */
public fun <K, V> MutableMap<K, V>.set(key: K, value: V): V? = this.put(key, value)
/**
* Converts this [[Map]] to a [[LinkedHashMap]] so future insertion orders are maintained
*/
public fun <K, V> Map<K, V>.toLinkedMap(): LinkedHashMap<K, V> = LinkedHashMap(this)
/** Provides indexed write access to mutable maps */
// this code is JVM-specific, because JS has native set function
public fun <K, V> MutableMap<K, V>.set(key: K, value: V): V? = put(key, value)
/**
* Converts this [[Map]] to a [[SortedMap]] so iteration order will be in key order
@@ -36,6 +29,25 @@ public fun <K, V> Map<K, V>.toSortedMap(comparator: Comparator<K>): SortedMap<K,
return result
}
/**
* Returns a new [[SortedMap]] populated with the given pairs where the first value in each pair
* is the key and the second value is the value
*
* @includeFunctionBody ../../test/collections/MapTest.kt createSortedMap
*/
public fun <K, V> sortedMapOf(vararg values: Pair<K, V>): SortedMap<K, V> {
val answer = TreeMap<K, V>()
/**
TODO replace by this simpler call when we can pass vararg values into other methods
answer.putAll(values)
*/
for (v in values) {
answer.put(v.first, v.second)
}
return answer
}
/**
* Converts this [[Map]] to a [[Properties]] object
*
@@ -192,8 +192,8 @@ class ArraysTest {
assertEquals(listOf("B"), array("A", "B", "C").slice(1..1))
assertEquals(listOf('E', 'B', 'C'), array('A', 'B', 'C', 'E').slice(iter))
assertTrue(array<Int>().slice(5..4).none())
assertTrue(array(1, 2, 3).slice(5..1).none())
assertEquals(listOf<Int>(), array<Int>().slice(5..4))
assertEquals(listOf<Int>(), array(1, 2, 3).slice(5..1))
assertEquals(listOf(2, 3, 9), array(2, 3, 9, 2, 3, 9).slice(iter))
assertEquals(listOf(2.0, 3.0), array(2.0, 3.0, 9.0).slice(0..1))
assertEquals(listOf(2f, 3f), array(2f, 3f, 9f).slice(0..1))