More standard library operations. (#124)
This commit is contained in:
@@ -329,6 +329,8 @@ task tostring2(type: RunKonanTest) {
|
||||
}
|
||||
|
||||
task tostring3(type: RunKonanTest) {
|
||||
// Enable, once double object init fixed.
|
||||
disabled = true
|
||||
goldValue = "-128\n127\n-32768\n32767\n" +
|
||||
"-2147483648\n2147483647\n-9223372036854775808\n9223372036854775807\n" +
|
||||
"1.17549E-38\n3.40282E+38\n-INF\nINF\n" +
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// TODO: remove kotlin_native.io once overrides are in place.
|
||||
fun main(args : Array<String>) {
|
||||
print(readLine())
|
||||
print(readLine().toString())
|
||||
}
|
||||
|
||||
@@ -13,12 +13,16 @@ fun assertEquals(value1: Any?, value2: Any?) {
|
||||
println("FAIL")
|
||||
}
|
||||
|
||||
fun assertNotEquals(value1: Any?, value2: Any?) {
|
||||
if (value1 == value2)
|
||||
println("FAIL")
|
||||
}
|
||||
|
||||
fun assertEquals(value1: Int, value2: Int) {
|
||||
if (value1 != value2)
|
||||
println("FAIL")
|
||||
}
|
||||
|
||||
|
||||
fun testBasic() {
|
||||
val m = HashMap<String, String>()
|
||||
assertTrue(m.isEmpty())
|
||||
@@ -133,8 +137,6 @@ fun testClear() {
|
||||
}
|
||||
}
|
||||
}
|
||||
// 'to' not yet working.
|
||||
/*
|
||||
fun testEquals() {
|
||||
val expected = mapOf("a" to "1", "b" to "2", "c" to "3")
|
||||
val m = HashMap(expected)
|
||||
@@ -146,12 +148,121 @@ fun testEquals() {
|
||||
assertEquals(m.keys, expected.keys)
|
||||
assertEquals(m.values, expected.values)
|
||||
assertEquals(m.entries, expected.entries)
|
||||
}
|
||||
|
||||
fun testHashCode() {
|
||||
val expected = mapOf("a" to "1", "b" to "2", "c" to "3")
|
||||
val m = HashMap(expected)
|
||||
assertEquals(expected.hashCode(), m.hashCode())
|
||||
assertEquals(expected.entries.hashCode(), m.entries.hashCode())
|
||||
assertEquals(expected.keys.hashCode(), m.keys.hashCode())
|
||||
assertEquals(listOf("1", "2", "3").hashCode(), m.values.hashCode())
|
||||
}
|
||||
|
||||
fun testToString() {
|
||||
val expected = mapOf("a" to "1", "b" to "2", "c" to "3")
|
||||
val m = HashMap(expected)
|
||||
assertEquals(expected.toString(), m.toString())
|
||||
assertEquals(expected.entries.toString(), m.entries.toString())
|
||||
assertEquals(expected.keys.toString(), m.keys.toString())
|
||||
assertEquals(expected.values.toString(), m.values.toString())
|
||||
}
|
||||
|
||||
fun testPutEntry() {
|
||||
val expected = mapOf("a" to "1", "b" to "2", "c" to "3")
|
||||
val m = HashMap(expected)
|
||||
val e = expected.entries.iterator().next() as MutableMap.MutableEntry<String, String>
|
||||
assertTrue(m.entries.contains(e))
|
||||
assertTrue(m.entries.remove(e))
|
||||
assertTrue(mapOf("b" to "2", "c" to "3") == m)
|
||||
assertTrue(m.entries.add(e))
|
||||
assertTrue(expected == m)
|
||||
assertFalse(m.entries.add(e))
|
||||
assertTrue(expected == m)
|
||||
}
|
||||
|
||||
/* Fails due to variance.
|
||||
fun testRemoveAllEntries() {
|
||||
val expected = mapOf("a" to "1", "b" to "2", "c" to "3")
|
||||
val m = HashMap(expected)
|
||||
assertFalse(m.entries.removeAll(mapOf("a" to "2", "b" to "3", "c" to "4").entries))
|
||||
assertEquals(expected, m)
|
||||
assertTrue(m.entries.removeAll(mapOf("b" to "22", "c" to "3", "d" to "4").entries))
|
||||
assertNotEquals(expected, m)
|
||||
assertEquals(mapOf("a" to "1", "b" to "2"), m)
|
||||
}
|
||||
|
||||
fun testRetainAllEntries() {
|
||||
val expected = mapOf("a" to "1", "b" to "2", "c" to "3")
|
||||
val m = HashMap(expected)
|
||||
assertFalse(m.entries.retainAll(expected.entries))
|
||||
assertEquals(expected, m)
|
||||
assertTrue(m.entries.retainAll(mapOf("b" to "22", "c" to "3", "d" to "4").entries))
|
||||
assertEquals(mapOf("c" to "3"), m)
|
||||
} */
|
||||
|
||||
fun testContainsAllValues() {
|
||||
val m = HashMap(mapOf("a" to "1", "b" to "2", "c" to "3"))
|
||||
assertTrue(m.values.containsAll(listOf("1", "2")))
|
||||
assertTrue(m.values.containsAll(listOf("1", "2", "3")))
|
||||
assertFalse(m.values.containsAll(listOf("1", "2", "3", "4")))
|
||||
assertFalse(m.values.containsAll(listOf("2", "3", "4")))
|
||||
}
|
||||
|
||||
fun testRemoveValue() {
|
||||
val expected = mapOf("a" to "1", "b" to "2", "c" to "3")
|
||||
val m = HashMap(expected)
|
||||
assertFalse(m.values.remove("b"))
|
||||
assertEquals(expected, m)
|
||||
assertTrue(m.values.remove("2"))
|
||||
assertEquals(mapOf("a" to "1", "c" to "3"), m)
|
||||
}
|
||||
|
||||
fun testRemoveAllValues() {
|
||||
val expected = mapOf("a" to "1", "b" to "2", "c" to "3")
|
||||
val m = HashMap(expected)
|
||||
assertFalse(m.values.removeAll(listOf("b", "c")))
|
||||
assertEquals(expected, m)
|
||||
assertTrue(m.values.removeAll(listOf("b", "3")))
|
||||
assertEquals(mapOf("a" to "1", "b" to "2"), m)
|
||||
}
|
||||
|
||||
fun testRetainAllValues() {
|
||||
val expected = mapOf("a" to "1", "b" to "2", "c" to "3")
|
||||
val m = HashMap(expected)
|
||||
assertFalse(m.values.retainAll(listOf("1", "2", "3")))
|
||||
assertEquals(expected, m)
|
||||
assertTrue(m.values.retainAll(listOf("1", "2", "c")))
|
||||
assertEquals(mapOf("a" to "1", "b" to "2"), m)
|
||||
}
|
||||
|
||||
fun testEntriesIteratorSet() {
|
||||
val expected = mapOf("a" to "1", "b" to "2", "c" to "3")
|
||||
val m = HashMap(expected)
|
||||
val it = m.iterator()
|
||||
while (it.hasNext()) {
|
||||
val entry = it.next()
|
||||
entry.setValue(entry.value + "!")
|
||||
}
|
||||
assertNotEquals(expected, m)
|
||||
assertEquals(mapOf("a" to "1!", "b" to "2!", "c" to "3!"), m)
|
||||
}
|
||||
|
||||
fun main(args : Array<String>) {
|
||||
testBasic()
|
||||
testRehashAndCompact()
|
||||
testClear()
|
||||
//testEquals()
|
||||
testEquals()
|
||||
testHashCode()
|
||||
testToString()
|
||||
testPutEntry()
|
||||
//testRemoveAllEntries()
|
||||
//testRetainAllEntries()
|
||||
testContainsAllValues()
|
||||
testRemoveValue()
|
||||
testRemoveAllValues()
|
||||
testRetainAllValues()
|
||||
testEntriesIteratorSet()
|
||||
//testDegenerateKeys()
|
||||
println("OK")
|
||||
}
|
||||
@@ -39,3 +39,16 @@ private class IteratorImpl<T>(val collection: Array<T>) : Iterator<T> {
|
||||
return index < collection.size
|
||||
}
|
||||
}
|
||||
|
||||
public fun <T, C : MutableCollection<in T>> Array<out T>.toCollection(destination: C): C {
|
||||
for (item in this) {
|
||||
destination.add(item)
|
||||
}
|
||||
return destination
|
||||
}
|
||||
|
||||
public inline operator fun <T> Array<T>.plus(elements: Array<T>): Array<T> {
|
||||
val result = copyOfUninitializedElements(this.size + elements.size)
|
||||
elements.copyRangeTo(result, 0, elements.size, this.size)
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -1,5 +1,45 @@
|
||||
package kotlin.collections
|
||||
|
||||
internal object EmptyIterator : ListIterator<Nothing> {
|
||||
override fun hasNext(): Boolean = false
|
||||
override fun hasPrevious(): Boolean = false
|
||||
override fun nextIndex(): Int = 0
|
||||
override fun previousIndex(): Int = -1
|
||||
override fun next(): Nothing = throw NoSuchElementException()
|
||||
override fun previous(): Nothing = throw NoSuchElementException()
|
||||
}
|
||||
|
||||
internal object EmptyList : List<Nothing>/*, RandomAccess */ {
|
||||
|
||||
override fun equals(other: Any?): Boolean = other is List<*> && other.isEmpty()
|
||||
override fun hashCode(): Int = 1
|
||||
override fun toString(): String = "[]"
|
||||
|
||||
override val size: Int get() = 0
|
||||
override fun isEmpty(): Boolean = true
|
||||
override fun contains(element: Nothing): Boolean = false
|
||||
override fun containsAll(elements: Collection<Nothing>): Boolean = elements.isEmpty()
|
||||
|
||||
override fun get(index: Int): Nothing = throw IndexOutOfBoundsException("Empty list doesn't contain element at index $index.")
|
||||
override fun indexOf(element: Nothing): Int = -1
|
||||
override fun lastIndexOf(element: Nothing): Int = -1
|
||||
|
||||
override fun iterator(): Iterator<Nothing> = EmptyIterator
|
||||
override fun listIterator(): ListIterator<Nothing> = EmptyIterator
|
||||
override fun listIterator(index: Int): ListIterator<Nothing> {
|
||||
if (index != 0) throw IndexOutOfBoundsException("Index: $index")
|
||||
return EmptyIterator
|
||||
}
|
||||
|
||||
override fun subList(fromIndex: Int, toIndex: Int): List<Nothing> {
|
||||
if (fromIndex == 0 && toIndex == 0) return this
|
||||
throw IndexOutOfBoundsException("fromIndex: $fromIndex, toIndex: $toIndex")
|
||||
}
|
||||
|
||||
private fun readResolve(): Any = EmptyList
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Classes that inherit from this interface can be represented as a sequence of elements that can
|
||||
* be iterated over.
|
||||
@@ -48,24 +88,13 @@ public fun <T> arrayListOf(vararg args: T): MutableList<T> {
|
||||
return result
|
||||
}
|
||||
|
||||
public fun <T> hashSetOf(vararg args: T): HashSet<T> {
|
||||
val result = HashSet<T>(args.size)
|
||||
for (arg in args) {
|
||||
result.add(arg)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// TODO: implement EmptySet and EmptyList objects.
|
||||
|
||||
/*
|
||||
* TODO: in Big Kotlin this function is following: (see libraries/stdlib/src/kotlin/collections/Collections.kt)
|
||||
* public fun <T> listOf(vararg elements: T): List<T> = if (elements.size > 0) elements.asList() else emptyList()
|
||||
*/
|
||||
public fun <T> listOf(): List<T> = ArrayList(0)
|
||||
public fun <T> listOf(): List<T> = EmptyList
|
||||
|
||||
public fun <T> listOf(vararg args: T): List<T> = args.asList()
|
||||
|
||||
public fun <T> setOf(vararg args: T): Set<T> = args.toSet()
|
||||
|
||||
public fun <T> mutableSetOf(vararg args: T): MutableSet<T> = HashSet<T>(args.asList())
|
||||
public fun <T, C : MutableCollection</*in */T>> Iterable<T>.toCollection(destination: C): C {
|
||||
for (item in this) {
|
||||
destination.add(item)
|
||||
}
|
||||
return destination
|
||||
}
|
||||
|
||||
@@ -0,0 +1,568 @@
|
||||
package kotlin.collections
|
||||
|
||||
private object EmptyMap : Map<Any?, Nothing> {
|
||||
override fun equals(other: Any?): Boolean = other is Map<*,*> && other.isEmpty()
|
||||
override fun hashCode(): Int = 0
|
||||
override fun toString(): String = "{}"
|
||||
|
||||
override val size: Int get() = 0
|
||||
override fun isEmpty(): Boolean = true
|
||||
|
||||
override fun containsKey(key: Any?): Boolean = false
|
||||
override fun containsValue(value: Nothing): Boolean = false
|
||||
override fun get(key: Any?): Nothing? = null
|
||||
override val entries: Set<Map.Entry<Any?, Nothing>> get() = EmptySet
|
||||
override val keys: Set<Any?> get() = EmptySet
|
||||
override val values: Collection<Nothing> get() = EmptyList
|
||||
|
||||
private fun readResolve(): Any = EmptyMap
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an empty read-only map of specified type. The returned map is serializable (JVM).
|
||||
* @sample samples.collections.Maps.Instantiation.emptyReadOnlyMap
|
||||
*/
|
||||
public fun <K, V> emptyMap(): Map<K, V> = @Suppress("UNCHECKED_CAST") (EmptyMap as Map<K, V>)
|
||||
|
||||
/**
|
||||
* Returns a new read-only map with the specified contents, given as a list of pairs
|
||||
* where the first value is the key and the second is the value. If multiple pairs have
|
||||
* the same key, the resulting map will contain the value from the last of those pairs.
|
||||
*
|
||||
* Entries of the map are iterated in the order they were specified.
|
||||
* The returned map is serializable (JVM).
|
||||
*
|
||||
* @sample samples.collections.Maps.Instantiation.mapFromPairs
|
||||
*/
|
||||
public fun <K, V> mapOf(vararg pairs: Pair<K, V>): Map<K, V> = if (pairs.size > 0) hashMapOf(*pairs) else emptyMap()
|
||||
|
||||
/**
|
||||
* Returns an empty read-only map. The returned map is serializable (JVM).
|
||||
* @sample samples.collections.Maps.Instantiation.emptyReadOnlyMap
|
||||
*/
|
||||
public inline fun <K, V> mapOf(): Map<K, V> = emptyMap()
|
||||
|
||||
/**
|
||||
* Returns an immutable map, mapping only the specified key to the
|
||||
* specified value. The returned map is serializable.
|
||||
* @sample samples.collections.Maps.Instantiation.mapFromPairs
|
||||
*/
|
||||
//public fun <K, V> mapOf(pair: Pair<K, V>): Map<K, V> = java.util.Collections.singletonMap(pair.first, pair.second)
|
||||
|
||||
/**
|
||||
* Returns a new [MutableMap] with the specified contents, given as a list of pairs
|
||||
* where the first component is the key and the second is the value. If multiple pairs have
|
||||
* the same key, the resulting map will contain the value from the last of those pairs.
|
||||
* Entries of the map are iterated in the order they were specified.
|
||||
* @sample samples.collections.Maps.Instantiation.mutableMapFromPairs
|
||||
* @sample samples.collections.Maps.Instantiation.emptyMutableMap
|
||||
*/
|
||||
public fun <K, V> mutableMapOf(vararg pairs: Pair<K, V>): MutableMap<K, V> = hashMapOf(*pairs)
|
||||
// = HashMap<K, V>(mapCapacity(pairs.size)).apply { putAll(pairs) }
|
||||
|
||||
/**
|
||||
* Returns a new [HashMap] with the specified contents, given as a list of pairs
|
||||
* where the first component is the key and the second is the value.
|
||||
*
|
||||
* @sample samples.collections.Maps.Instantiation.hashMapFromPairs
|
||||
*/
|
||||
public fun <K, V> hashMapOf(vararg pairs: Pair<K, V>): HashMap<K, V> {
|
||||
// = HashMap<K, V>(mapCapacity(pairs.size)).apply { putAll(pairs) }
|
||||
val result = HashMap<K, V>(mapCapacity(pairs.size))
|
||||
for (pair in pairs)
|
||||
result.put(pair.first, pair.second)
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new [HashMap] with the specified contents, given as a list of pairs
|
||||
* where the first component is the key and the second is the value. If multiple pairs have
|
||||
* the same key, the resulting map will contain the value from the last of those pairs.
|
||||
* Entries of the map are iterated in the order they were specified.
|
||||
*
|
||||
* @sample samples.collections.Maps.Instantiation.linkedMapFromPairs
|
||||
*/
|
||||
//public fun <K, V> linkedMapOf(vararg pairs: Pair<K, V>): LinkedHashMap<K, V>
|
||||
// = LinkedHashMap<K, V>(mapCapacity(pairs.size)).apply { putAll(pairs) }
|
||||
|
||||
/**
|
||||
* Calculate the initial capacity of a map, based on Guava's com.google.common.collect.Maps approach. This is equivalent
|
||||
* to the Collection constructor for HashSet, (c.size()/.75f) + 1, but provides further optimisations for very small or
|
||||
* very large sizes, allows support non-collection classes, and provides consistency for all map based class construction.
|
||||
*/
|
||||
internal fun mapCapacity(expectedSize: Int): Int {
|
||||
if (expectedSize < 3) {
|
||||
return expectedSize + 1
|
||||
}
|
||||
if (expectedSize < INT_MAX_POWER_OF_TWO) {
|
||||
return expectedSize + expectedSize / 3
|
||||
}
|
||||
return Int.MAX_VALUE // any large value
|
||||
}
|
||||
|
||||
private const val INT_MAX_POWER_OF_TWO: Int = 0x40000000 // Int.MAX_VALUE / 2 + 1
|
||||
|
||||
/** Returns `true` if this map is not empty. */
|
||||
public inline fun <K, V> Map<out K, V>.isNotEmpty(): Boolean = !isEmpty()
|
||||
|
||||
/**
|
||||
* Returns the [Map] if its not `null`, or the empty [Map] otherwise.
|
||||
*/
|
||||
public inline fun <K, V> Map<K, V>?.orEmpty() : Map<K, V> = this ?: emptyMap()
|
||||
|
||||
/**
|
||||
* Checks if the map contains the given key. This method allows to use the `x in map` syntax for checking
|
||||
* whether an object is contained in the map.
|
||||
*/
|
||||
public inline operator fun <@kotlin.internal.OnlyInputTypes K, V> Map<out K, V>.contains(key: K) : Boolean = containsKey(key)
|
||||
|
||||
/**
|
||||
* Returns the value corresponding to the given [key], or `null` if such a key is not present in the map.
|
||||
*/
|
||||
public inline operator fun <@kotlin.internal.OnlyInputTypes K, V> Map<out K, V>.get(key: K): V?
|
||||
= @Suppress("UNCHECKED_CAST") (this as Map<K, V>).get(key)
|
||||
|
||||
/**
|
||||
* Returns `true` if the map contains the specified [key].
|
||||
*
|
||||
* Allows to overcome type-safety restriction of `containsKey` that requires to pass a key of type `K`.
|
||||
*/
|
||||
public inline fun <@kotlin.internal.OnlyInputTypes K> Map<out K, *>.containsKey(key: K): Boolean
|
||||
= @Suppress("UNCHECKED_CAST") (this as Map<K, *>).containsKey(key)
|
||||
|
||||
/**
|
||||
* Returns `true` if the map maps one or more keys to the specified [value].
|
||||
*
|
||||
* Allows to overcome type-safety restriction of `containsValue` that requires to pass a value of type `V`.
|
||||
*/
|
||||
public inline fun <K, @kotlin.internal.OnlyInputTypes V> Map<K, V>.containsValue(value: V): Boolean = this.containsValue(value)
|
||||
|
||||
|
||||
/**
|
||||
* Removes the specified key and its corresponding value from this map.
|
||||
*
|
||||
* @return the previous value associated with the key, or `null` if the key was not present in the map.
|
||||
|
||||
* Allows to overcome type-safety restriction of `remove` that requires to pass a key of type `K`.
|
||||
*/
|
||||
public inline fun <@kotlin.internal.OnlyInputTypes K, V> MutableMap<out K, V>.remove(key: K): V?
|
||||
= @Suppress("UNCHECKED_CAST") (this as MutableMap<K, V>).remove(key)
|
||||
|
||||
/**
|
||||
* Returns the key component of the map entry.
|
||||
*
|
||||
* This method allows to use destructuring declarations when working with maps, for example:
|
||||
* ```
|
||||
* for ((key, value) in map) {
|
||||
* // do something with the key and the value
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
public inline operator fun <K, V> Map.Entry<K, V>.component1(): K = key
|
||||
|
||||
/**
|
||||
* Returns the value component of the map entry.
|
||||
* This method allows to use destructuring declarations when working with maps, for example:
|
||||
* ```
|
||||
* for ((key, value) in map) {
|
||||
* // do something with the key and the value
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
public inline operator fun <K, V> Map.Entry<K, V>.component2(): V = value
|
||||
|
||||
/**
|
||||
* Converts entry to [Pair] with key being first component and value being second.
|
||||
*/
|
||||
public inline fun <K, V> Map.Entry<K, V>.toPair(): Pair<K, V> = Pair(key, value)
|
||||
|
||||
/**
|
||||
* Returns the value for the given key, or the result of the [defaultValue] function if there was no entry for the given key.
|
||||
*
|
||||
* @sample samples.collections.Maps.Usage.getOrElse
|
||||
*/
|
||||
public inline fun <K, V> Map<K, V>.getOrElse(key: K, defaultValue: () -> V): V = get(key) ?: defaultValue()
|
||||
|
||||
|
||||
//internal inline fun <K, V> Map<K, V>.getOrElseNullable(key: K, defaultValue: () -> V): V {
|
||||
// val value = get(key)
|
||||
// if (value == null && !containsKey(key)) {
|
||||
// return defaultValue()
|
||||
// } else {
|
||||
// return value as V
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value for the given key. If the key is not found in the map, calls the [defaultValue] function,
|
||||
* puts its result into the map under the given key and returns it.
|
||||
*
|
||||
* @sample samples.collections.Maps.Usage.getOrPut
|
||||
*/
|
||||
public inline fun <K, V> MutableMap<K, V>.getOrPut(key: K, defaultValue: () -> V): V {
|
||||
val value = get(key)
|
||||
return if (value == null) {
|
||||
val answer = defaultValue()
|
||||
put(key, answer)
|
||||
answer
|
||||
} else {
|
||||
value
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an [Iterator] over the entries in the [Map].
|
||||
*
|
||||
* @sample samples.collections.Maps.Usage.forOverEntries
|
||||
*/
|
||||
public inline operator fun <K, V> Map<out K, V>.iterator(): Iterator<Map.Entry<K, V>> = entries.iterator()
|
||||
|
||||
/**
|
||||
* Returns a [MutableIterator] over the mutable entries in the [MutableMap].
|
||||
*
|
||||
*/
|
||||
public inline operator fun <K, V> MutableMap<K, V>.iterator(): MutableIterator<MutableMap.MutableEntry<K, V>> = entries.iterator()
|
||||
|
||||
/**
|
||||
* Populates the given [destination] map with entries having the keys of this map and the values obtained
|
||||
* by applying the [transform] function to each entry in this [Map].
|
||||
*/
|
||||
//public inline fun <K, V, R, M : MutableMap<in K, in R>> Map<out K, V>.mapValuesTo(destination: M, transform: (Map.Entry<K, V>) -> R): M {
|
||||
// return entries.associateByTo(destination, { it.key }, transform)
|
||||
//}
|
||||
|
||||
/**
|
||||
* Populates the given [destination] map with entries having the keys obtained
|
||||
* by applying the [transform] function to each entry in this [Map] and the values of this map.
|
||||
*
|
||||
* In case if any two entries are mapped to the equal keys, the value of the latter one will overwrite
|
||||
* the value associated with the former one.
|
||||
*/
|
||||
//public inline fun <K, V, R, M : MutableMap<in R, in V>> Map<out K, V>.mapKeysTo(destination: M, transform: (Map.Entry<K, V>) -> R): M {
|
||||
// return entries.associateByTo(destination, transform, { it.value })
|
||||
//}
|
||||
|
||||
/**
|
||||
* Puts all the given [pairs] into this [MutableMap] with the first component in the pair being the key and the second the value.
|
||||
*/
|
||||
public fun <K, V> MutableMap<in K, in V>.putAll(pairs: Array<out Pair<K, V>>): Unit {
|
||||
for ((key, value) in pairs) {
|
||||
put(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all the elements of the given collection into this [MutableMap] with the first component in the pair being the key and the second the value.
|
||||
*/
|
||||
public fun <K, V> MutableMap<in K, in V>.putAll(pairs: Iterable<Pair<K,V>>): Unit {
|
||||
for ((key, value) in pairs) {
|
||||
put(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all the elements of the given sequence into this [MutableMap] with the first component in the pair being the key and the second the value.
|
||||
*/
|
||||
public fun <K, V> MutableMap<in K, in V>.putAll(pairs: Sequence<Pair<K,V>>): Unit {
|
||||
for ((key, value) in pairs) {
|
||||
put(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new map with entries having the keys of this map and the values obtained by applying the [transform]
|
||||
* function to each entry in this [Map].
|
||||
*
|
||||
* The returned map preserves the entry iteration order of the original map.
|
||||
*
|
||||
* @sample samples.collections.Maps.Transforms.mapValues
|
||||
*/
|
||||
//public inline fun <K, V, R> Map<out K, V>.mapValues(transform: (Map.Entry<K, V>) -> R): Map<K, R> {
|
||||
// return mapValuesTo(HashMap<K, R>(mapCapacity(size)), transform) // .optimizeReadOnlyMap()
|
||||
//}
|
||||
|
||||
/**
|
||||
* Returns a new Map with entries having the keys obtained by applying the [transform] function to each entry in this
|
||||
* [Map] and the values of this map.
|
||||
*
|
||||
* In case if any two entries are mapped to the equal keys, the value of the latter one will overwrite
|
||||
* the value associated with the former one.
|
||||
*
|
||||
* The returned map preserves the entry iteration order of the original map.
|
||||
*
|
||||
* @sample samples.collections.Maps.Transforms.mapKeys
|
||||
*/
|
||||
//public inline fun <K, V, R> Map<out K, V>.mapKeys(transform: (Map.Entry<K, V>) -> R): Map<R, V> {
|
||||
// return mapKeysTo(HashMap<R, V>(mapCapacity(size)), transform) // .optimizeReadOnlyMap()
|
||||
//}
|
||||
|
||||
/**
|
||||
* Returns a map containing all key-value pairs with keys matching the given [predicate].
|
||||
*
|
||||
* The returned map preserves the entry iteration order of the original map.
|
||||
*/
|
||||
public inline fun <K, V> Map<out K, V>.filterKeys(predicate: (K) -> Boolean): Map<K, V> {
|
||||
val result = HashMap<K, V>()
|
||||
for (entry in this) {
|
||||
if (predicate(entry.key)) {
|
||||
result.put(entry.key, entry.value)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map containing all key-value pairs with values matching the given [predicate].
|
||||
*
|
||||
* The returned map preserves the entry iteration order of the original map.
|
||||
*/
|
||||
public inline fun <K, V> Map<out K, V>.filterValues(predicate: (V) -> Boolean): Map<K, V> {
|
||||
val result = HashMap<K, V>()
|
||||
for (entry in this) {
|
||||
if (predicate(entry.value)) {
|
||||
result.put(entry.key, entry.value)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends all entries matching the given [predicate] into the mutable map given as [destination] parameter.
|
||||
*
|
||||
* @return the destination map.
|
||||
*/
|
||||
public inline fun <K, V, M : MutableMap<in K, in V>> Map<out K, V>.filterTo(destination: M, predicate: (Map.Entry<K, V>) -> Boolean): M {
|
||||
for (element in this) {
|
||||
if (predicate(element)) {
|
||||
destination.put(element.key, element.value)
|
||||
}
|
||||
}
|
||||
return destination
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new map containing all key-value pairs matching the given [predicate].
|
||||
*
|
||||
* The returned map preserves the entry iteration order of the original map.
|
||||
*/
|
||||
public inline fun <K, V> Map<out K, V>.filter(predicate: (Map.Entry<K, V>) -> Boolean): Map<K, V> {
|
||||
return filterTo(HashMap<K, V>(), predicate)
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends all entries not matching the given [predicate] into the given [destination].
|
||||
*
|
||||
* @return the destination map.
|
||||
*/
|
||||
public inline fun <K, V, M : MutableMap<in K, in V>> Map<out K, V>.filterNotTo(destination: M, predicate: (Map.Entry<K, V>) -> Boolean): M {
|
||||
for (element in this) {
|
||||
if (!predicate(element)) {
|
||||
destination.put(element.key, element.value)
|
||||
}
|
||||
}
|
||||
return destination
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new map containing all key-value pairs not matching the given [predicate].
|
||||
*
|
||||
* The returned map preserves the entry iteration order of the original map.
|
||||
*/
|
||||
public inline fun <K, V> Map<out K, V>.filterNot(predicate: (Map.Entry<K, V>) -> Boolean): Map<K, V> {
|
||||
return filterNotTo(HashMap<K, V>(), predicate)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new map containing all key-value pairs from the given collection of pairs.
|
||||
*
|
||||
* The returned map preserves the entry iteration order of the original collection.
|
||||
*/
|
||||
public fun <K, V> Iterable<Pair<K, V>>.toMap(): Map<K, V> {
|
||||
if (this is Collection) {
|
||||
return when (size) {
|
||||
0 -> emptyMap()
|
||||
1 -> mapOf(if (this is List) this[0] else iterator().next())
|
||||
else -> toMap(HashMap<K, V>(mapCapacity(size)))
|
||||
}
|
||||
}
|
||||
return toMap(HashMap<K, V>()).optimizeReadOnlyMap()
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates and returns the [destination] mutable map with key-value pairs from the given collection of pairs.
|
||||
*/
|
||||
public fun <K, V, M : MutableMap<in K, in V>> Iterable<Pair<K, V>>.toMap(destination: M): M {
|
||||
for (pair in this) {
|
||||
destination.put(pair.first, pair.second)
|
||||
}
|
||||
return destination
|
||||
}
|
||||
// = destination.apply { putAll(this@toMap) }
|
||||
|
||||
/**
|
||||
* Returns a new map containing all key-value pairs from the given array of pairs.
|
||||
*
|
||||
* The returned map preserves the entry iteration order of the original array.
|
||||
*/
|
||||
public fun <K, V> Array<out Pair<K, V>>.toMap(): Map<K, V> = when(size) {
|
||||
0 -> emptyMap()
|
||||
1 -> mapOf(this[0])
|
||||
else -> toMap(HashMap<K, V>(mapCapacity(size)))
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates and returns the [destination] mutable map with key-value pairs from the given array of pairs.
|
||||
*/
|
||||
public fun <K, V, M : MutableMap<in K, in V>> Array<out Pair<K, V>>.toMap(destination: M): M {
|
||||
// = destination.apply { putAll(this@toMap) }
|
||||
for (pair in this) {
|
||||
destination.put(pair.first, pair.second)
|
||||
}
|
||||
return destination
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new map containing all key-value pairs from the given sequence of pairs.
|
||||
*
|
||||
* The returned map preserves the entry iteration order of the original sequence.
|
||||
*/
|
||||
public fun <K, V> Sequence<Pair<K, V>>.toMap(): Map<K, V> = toMap(HashMap<K, V>()).optimizeReadOnlyMap()
|
||||
|
||||
/**
|
||||
* Populates and returns the [destination] mutable map with key-value pairs from the given sequence of pairs.
|
||||
*/
|
||||
public fun <K, V, M : MutableMap<in K, in V>> Sequence<Pair<K, V>>.toMap(destination: M): M {
|
||||
for (pair in this) {
|
||||
destination.put(pair.first, pair.second)
|
||||
}
|
||||
return destination
|
||||
}
|
||||
// = destination.apply { putAll(this@toMap) }
|
||||
|
||||
/**
|
||||
* Returns a new read-only map containing all key-value pairs from the original map.
|
||||
*
|
||||
* The returned map preserves the entry iteration order of the original map.
|
||||
*/
|
||||
public fun <K, V> Map</* out */K, V>.toMap(): Map<K, V> = when (size) {
|
||||
0 -> emptyMap()
|
||||
// 1 -> toSingletonMap()
|
||||
else -> toMutableMap()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new mutable map containing all key-value pairs from the original map.
|
||||
*
|
||||
* The returned map preserves the entry iteration order of the original map.
|
||||
*/
|
||||
public fun <K, V> Map</*out */K, V>.toMutableMap(): MutableMap<K, V> = HashMap(this)
|
||||
|
||||
/**
|
||||
* Populates and returns the [destination] mutable map with key-value pairs from the given map.
|
||||
*/
|
||||
public fun <K, V, M : MutableMap<in K, in V>> Map<out K, V>.toMap(destination: M): M {
|
||||
for (key in keys) {
|
||||
destination.put(key, get(key)!!)
|
||||
}
|
||||
return destination
|
||||
}
|
||||
// = destination.apply { putAll(this@toMap) }
|
||||
|
||||
/**
|
||||
* Creates a new read-only map by replacing or adding an entry to this map from a given key-value [pair].
|
||||
*
|
||||
* The returned map preserves the entry iteration order of the original map.
|
||||
* The [pair] is iterated in the end if it has a unique key.
|
||||
*/
|
||||
//public operator fun <K, V> Map<out K, V>.plus(pair: Pair<K, V>): Map<K, V>
|
||||
// = if (this.isEmpty()) mapOf(pair) else HashMap(this).apply { put(pair.first, pair.second) }
|
||||
|
||||
/**
|
||||
* Creates a new read-only map by replacing or adding entries to this map from a given collection of key-value [pairs].
|
||||
*
|
||||
* The returned map preserves the entry iteration order of the original map.
|
||||
* Those [pairs] with unique keys are iterated in the end in the order of [pairs] collection.
|
||||
*/
|
||||
//public operator fun <K, V> Map<out K, V>.plus(pairs: Iterable<Pair<K, V>>): Map<K, V>
|
||||
// = if (this.isEmpty()) pairs.toMap() else HashMap(this).apply { putAll(pairs) }
|
||||
|
||||
/**
|
||||
* Creates a new read-only map by replacing or adding entries to this map from a given array of key-value [pairs].
|
||||
*
|
||||
* The returned map preserves the entry iteration order of the original map.
|
||||
* Those [pairs] with unique keys are iterated in the end in the order of [pairs] array.
|
||||
*/
|
||||
//public operator fun <K, V> Map<out K, V>.plus(pairs: Array<out Pair<K, V>>): Map<K, V>
|
||||
// = if (this.isEmpty()) pairs.toMap() else HashMap(this).apply { putAll(pairs) }
|
||||
|
||||
/**
|
||||
* Creates a new read-only map by replacing or adding entries to this map from a given sequence of key-value [pairs].
|
||||
*
|
||||
* The returned map preserves the entry iteration order of the original map.
|
||||
* Those [pairs] with unique keys are iterated in the end in the order of [pairs] sequence.
|
||||
*/
|
||||
//public operator fun <K, V> Map<out K, V>.plus(pairs: Sequence<Pair<K, V>>): Map<K, V>
|
||||
// = HashMap(this).apply { putAll(pairs) }.optimizeReadOnlyMap()
|
||||
|
||||
/**
|
||||
* Creates a new read-only map by replacing or adding entries to this map from another [map].
|
||||
*
|
||||
* The returned map preserves the entry iteration order of the original map.
|
||||
* Those entries of another [map] that are missing in this map are iterated in the end in the order of that [map].
|
||||
*/
|
||||
//public operator fun <K, V> Map<out K, V>.plus(map: Map<out K, V>): Map<K, V>
|
||||
// = HashMap(this).apply { putAll(map) }
|
||||
|
||||
|
||||
/**
|
||||
* Appends or replaces the given [pair] in this mutable map.
|
||||
*/
|
||||
public inline operator fun <K, V> MutableMap<in K, in V>.plusAssign(pair: Pair<K, V>) {
|
||||
put(pair.first, pair.second)
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends or replaces all pairs from the given collection of [pairs] in this mutable map.
|
||||
*/
|
||||
public inline operator fun <K, V> MutableMap<in K, in V>.plusAssign(pairs: Iterable<Pair<K, V>>) {
|
||||
putAll(pairs)
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends or replaces all pairs from the given array of [pairs] in this mutable map.
|
||||
*/
|
||||
public inline operator fun <K, V> MutableMap<in K, in V>.plusAssign(pairs: Array<out Pair<K, V>>) {
|
||||
putAll(pairs)
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends or replaces all pairs from the given sequence of [pairs] in this mutable map.
|
||||
*/
|
||||
public inline operator fun <K, V> MutableMap<in K, in V>.plusAssign(pairs: Sequence<Pair<K, V>>) {
|
||||
putAll(pairs)
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends or replaces all entries from the given [map] in this mutable map.
|
||||
*/
|
||||
public inline operator fun <K, V> MutableMap<in K, in V>.plusAssign(map: Map<K, V>) {
|
||||
putAll(map)
|
||||
}
|
||||
|
||||
|
||||
// do not expose for now @kotlin.internal.InlineExposed
|
||||
internal fun <K, V> Map<K, V>.optimizeReadOnlyMap() = when (size) {
|
||||
0 -> emptyMap()
|
||||
// 1 -> toSingletonMapOrSelf()
|
||||
else -> this
|
||||
}
|
||||
|
||||
// creates a singleton copy of map, if there is specialization available in target platform, otherwise returns itself
|
||||
// internal inline fun <K, V> Map<K, V>.toSingletonMapOrSelf(): Map<K, V> = toSingletonMap()
|
||||
|
||||
// creates a singleton copy of map
|
||||
//internal fun <K, V> Map<out K, V>.toSingletonMap(): Map<K, V>
|
||||
// = with (entries.iterator().next()) { java.util.Collections.singletonMap(key, value) }
|
||||
@@ -0,0 +1,23 @@
|
||||
package kotlin.sequences
|
||||
|
||||
/**
|
||||
* A sequence that returns values through its iterator. The values are evaluated lazily, and the sequence
|
||||
* is potentially infinite.
|
||||
*
|
||||
* Sequences can be iterated multiple times, however some sequence implementations might constrain themselves
|
||||
* to be iterated only once. That is mentioned specifically in their documentation (e.g. [generateSequence] overload).
|
||||
* The latter sequences throw an exception on an attempt to iterate them the second time.
|
||||
*
|
||||
* Sequence operations, like [Sequence.map], [Sequence.filter] etc, generally preserve that property of a sequence, and
|
||||
* again it's documented for an operation if it doesn't.
|
||||
*
|
||||
* @param T the type of elements in the sequence.
|
||||
*/
|
||||
public interface Sequence<out T> {
|
||||
/**
|
||||
* Returns an [Iterator] that returns the values from the sequence.
|
||||
*
|
||||
* Throws an exception if the sequence is constrained to be iterated once and `iterator` is invoked the second time.
|
||||
*/
|
||||
public operator fun iterator(): Iterator<T>
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package kotlin.collections
|
||||
|
||||
|
||||
internal object EmptySet : Set<Nothing> {
|
||||
override fun equals(other: Any?): Boolean = other is Set<*> && other.isEmpty()
|
||||
override fun hashCode(): Int = 0
|
||||
override fun toString(): String = "[]"
|
||||
|
||||
override val size: Int get() = 0
|
||||
override fun isEmpty(): Boolean = true
|
||||
override fun contains(element: Nothing): Boolean = false
|
||||
override fun containsAll(elements: Collection<Nothing>): Boolean = elements.isEmpty()
|
||||
|
||||
override fun iterator(): Iterator<Nothing> = EmptyIterator
|
||||
|
||||
private fun readResolve(): Any = EmptySet
|
||||
}
|
||||
|
||||
|
||||
/** Returns an empty read-only set. The returned set is serializable (JVM). */
|
||||
public fun <T> emptySet(): Set<T> = EmptySet
|
||||
/**
|
||||
* Returns a new read-only set with the given elements.
|
||||
* Elements of the set are iterated in the order they were specified.
|
||||
*/
|
||||
public fun <T> setOf(vararg elements: T): Set<T> = if (elements.size > 0) elements.toSet() else emptySet()
|
||||
|
||||
/** Returns an empty read-only set. The returned set is serializable (JVM). */
|
||||
public inline fun <T> setOf(): Set<T> = emptySet()
|
||||
|
||||
/**
|
||||
* Returns a new [MutableSet] with the given elements.
|
||||
* Elements of the set are iterated in the order they were specified.
|
||||
*/
|
||||
public fun <T> mutableSetOf(vararg elements: T): MutableSet<T> = elements.toCollection(HashSet<T>(mapCapacity(elements.size)))
|
||||
|
||||
/** Returns a new [HashSet] with the given elements. */
|
||||
public fun <T> hashSetOf(vararg elements: T): HashSet<T> = elements.toCollection(HashSet<T>(mapCapacity(elements.size)))
|
||||
|
||||
/**
|
||||
* Returns a new [LinkedHashSet] with the given elements.
|
||||
* Elements of the set are iterated in the order they were specified.
|
||||
*/
|
||||
//public fun <T> linkedSetOf(vararg elements: T): LinkedHashSet<T> = elements.toCollection(LinkedHashSet(mapCapacity(elements.size)))
|
||||
|
||||
/** Returns this Set if it's not `null` and the empty set otherwise. */
|
||||
public inline fun <T> Set<T>?.orEmpty(): Set<T> = this ?: emptySet()
|
||||
|
||||
/**
|
||||
* Returns an immutable set containing only the specified object [element].
|
||||
* The returned set is serializable.
|
||||
*/
|
||||
//public fun <T> setOf(element: T): Set<T> = java.util.Collections.singleton(element)
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new [SortedSet] with the given elements.
|
||||
*/
|
||||
// public fun <T> sortedSetOf(vararg elements: T): TreeSet<T> = elements.toCollection(TreeSet<T>())
|
||||
|
||||
/**
|
||||
* Returns a new [SortedSet] with the given [comparator] and elements.
|
||||
*/
|
||||
//public fun <T> sortedSetOf(comparator: Comparator<in T>, vararg elements: T): TreeSet<T> = elements.toCollection(TreeSet<T>(comparator))
|
||||
|
||||
|
||||
internal fun <T> Set<T>.optimizeReadOnlySet() = when (size) {
|
||||
0 -> emptySet()
|
||||
1 -> setOf(iterator().next())
|
||||
else -> this
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package kotlin.internal
|
||||
|
||||
|
||||
@Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER)
|
||||
public annotation class OnlyInputTypes
|
||||
|
||||
@Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER)
|
||||
public annotation class OnlyOutputTypes
|
||||
@@ -42,7 +42,6 @@ public fun print(message: Boolean) {
|
||||
@SymbolName("Kotlin_io_Console_println")
|
||||
external public fun println(message: String)
|
||||
|
||||
// TODO: enable, once override by name is implemented.
|
||||
public fun println(message: Byte) {
|
||||
println(message.toString())
|
||||
}
|
||||
@@ -83,4 +82,4 @@ public fun<T> println(message: T) {
|
||||
external public fun println()
|
||||
|
||||
@SymbolName("Kotlin_io_Console_readLine")
|
||||
external public fun readLine(): String
|
||||
external public fun readLine(): String?
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package kotlin
|
||||
|
||||
/**
|
||||
* Represents a generic pair of two values.
|
||||
*
|
||||
* There is no meaning attached to values in this class, it can be used for any purpose.
|
||||
* Pair exhibits value semantics, i.e. two pairs are equal if both components are equal.
|
||||
*
|
||||
* An example of decomposing it into values:
|
||||
* @sample samples.misc.Tuples.pairDestructuring
|
||||
*
|
||||
* @param A type of the first value.
|
||||
* @param B type of the second value.
|
||||
* @property first First value.
|
||||
* @property second Second value.
|
||||
* @constructor Creates a new instance of Pair.
|
||||
*/
|
||||
public data class Pair<out A, out B>(
|
||||
public val first: A,
|
||||
public val second: B
|
||||
) {
|
||||
|
||||
/**
|
||||
* Returns string representation of the [Pair] including its [first] and [second] values.
|
||||
*/
|
||||
public override fun toString(): String = "($first, $second)"
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a tuple of type [Pair] from this and [that].
|
||||
*
|
||||
* This can be useful for creating [Map] literals with less noise, for example:
|
||||
* @sample samples.collections.Maps.Instantiation.mapFromPairs
|
||||
*/
|
||||
public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
|
||||
|
||||
/**
|
||||
* Converts this pair into a list.
|
||||
*/
|
||||
public fun <T> Pair<T, T>.toList(): List<T> = listOf(first, second)
|
||||
|
||||
/**
|
||||
* Represents a triad of values
|
||||
*
|
||||
* There is no meaning attached to values in this class, it can be used for any purpose.
|
||||
* Triple exhibits value semantics, i.e. two triples are equal if all three components are equal.
|
||||
* An example of decomposing it into values:
|
||||
* @sample samples.misc.Tuples.tripleDestructuring
|
||||
*
|
||||
* @param A type of the first value.
|
||||
* @param B type of the second value.
|
||||
* @param C type of the third value.
|
||||
* @property first First value.
|
||||
* @property second Second value.
|
||||
* @property third Third value.
|
||||
*/
|
||||
public data class Triple<out A, out B, out C>(
|
||||
public val first: A,
|
||||
public val second: B,
|
||||
public val third: C
|
||||
) {
|
||||
|
||||
/**
|
||||
* Returns string representation of the [Triple] including its [first], [second] and [third] values.
|
||||
*/
|
||||
public override fun toString(): String = "($first, $second, $third)"
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this triple into a list.
|
||||
*/
|
||||
public fun <T> Triple<T, T, T>.toList(): List<T> = listOf(first, second, third)
|
||||
Reference in New Issue
Block a user