Merge pull request #495 from JetBrains/rr/stdlib_maps

Map-related fixes and improvements in stdlib.
This commit is contained in:
Ilya Ryzhenkov
2014-07-17 01:30:24 +04:00
25 changed files with 586 additions and 305 deletions
@@ -61,7 +61,7 @@ public class PseudocodeVariableDataCollector(
// Variables declared in an inner (deeper) scope can't be accessed from an outer scope.
// Thus they can be filtered out upon leaving the inner scope.
return data.filterKeys { variable ->
return data.filterKeys_tmp { variable ->
val lexicalScope = lexicalScopeVariableInfo.declaredIn[variable]
// '-1' for variables declared outside this pseudocode
val depth = lexicalScope?.depth ?: -1
@@ -19,7 +19,8 @@ package org.jetbrains.jet.utils.addToStdlib
import java.util.HashMap
import java.util.Collections
fun <K, V> Map<K, V>.filterKeys(predicate: (K)->Boolean): Map<K, V> {
deprecated("Replace with filterKeys when bootstrapped")
fun <K, V> Map<K, V>.filterKeys_tmp(predicate: (K)->Boolean): Map<K, V> {
val result = HashMap<K, V>()
for ((k, v) in this) {
if (predicate(k)) {
@@ -43,7 +43,7 @@ public class NavigateToStdlibSourceRegressionTest extends NavigateToLibraryRegre
}
public void testJavaClass() throws IOException {
doNavigationInSourcesTest("libraries/stdlib/src/kotlin/collections/Maps.kt", "Collections", "java.util.Collections");
doNavigationInSourcesTest("libraries/stdlib/src/kotlin/collections/Iterators.kt", "Enumeration", "java.util.Enumeration");
}
public void testKotlinClass() throws IOException {
@@ -68,7 +68,7 @@ public class NavigateToStdlibSourceRegressionTest extends NavigateToLibraryRegre
PsiFile psiFile = getPsiFileForFileFromSources(file);
String text = psiFile.getText();
int index = text.indexOf(element);
assertNotSame(-1, "Cannot find text '" + element + "' in file " + path);
assertNotSame("Cannot find text '" + element + "' in file " + path, -1, index);
while (Character.isLetter(text.charAt(index - 1))) {
index = text.indexOf(element, index + 1);
}
+3 -2
View File
@@ -8,8 +8,9 @@ import java.lang.*;
native
public val noImpl : Nothing = throw Exception()
// Drop this after KT-2093 will be fixed and restore MutableMap.set in Maps.kt from MapsJVM.kt
/** Provides [] access to maps */
native public fun <K, V> MutableMap<K, V>.set(key: K, value: V): Unit = noImpl
native public fun <K, V> MutableMap<K, V>.set(key: K, value: V): V? = noImpl
library("println")
public fun println() {}
@@ -22,4 +23,4 @@ native public fun parseInt(s: String, radix: Int = 10): Int = js.noImpl
library
public fun safeParseInt(s : String) : Int? = js.noImpl
library
public fun safeParseDouble(s : String) : Double? = js.noImpl
public fun safeParseDouble(s : String) : Double? = js.noImpl
@@ -19,7 +19,7 @@ package org.jetbrains.k2js.test.semantics;
import junit.framework.Test;
@SuppressWarnings("JUnitTestCaseWithNoTests")
public final class ArraysTest extends JsUnitTestBase {
public final class StdLibArraysTest extends JsUnitTestBase {
public static Test suite() throws Exception {
return createTestSuiteForFile("libraries/stdlib/test/collections/ArraysTest.kt");
}
@@ -20,7 +20,7 @@ import junit.framework.Test;
//NOTE: well, it has tests
@SuppressWarnings("JUnitTestCaseWithNoTests")
public final class BitwiseOperationsTest extends JsUnitTestBase {
public final class StdLibBitwiseOperationsTest extends JsUnitTestBase {
public static Test suite() throws Exception {
return createTestSuiteForFile("libraries/stdlib/test/language/BitwiseOperationsTest.kt");
}
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2013 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 org.jetbrains.k2js.test.semantics;
import junit.framework.Test;
@SuppressWarnings("JUnitTestCaseWithNoTests")
public final class StdLibMapTest extends JsUnitTestBase {
public static Test suite() throws Exception {
return createTestSuiteForFile("libraries/stdlib/test/collections/MapTest.kt");
}
}
+11 -27
View File
@@ -68,6 +68,8 @@
};
function hashObject(obj) {
if (obj == null) return "";
var hashCode;
if (typeof obj == "string") {
return obj;
@@ -97,23 +99,11 @@
}
function equals_fixedValueNoEquals(fixedValue, variableValue) {
return (typeof variableValue.equals_za3rmp$ == FUNCTION) ?
return (variableValue != null && typeof variableValue.equals_za3rmp$ == FUNCTION) ?
// TODO: test this case
variableValue.equals_za3rmp$(fixedValue) : (fixedValue === variableValue);
}
function createKeyValCheck(kvStr) {
return function (kv) {
if (kv === null) {
throw new Error("null is not a valid " + kvStr);
}
else if (typeof kv == "undefined") {
throw new Error(kvStr + " must not be undefined");
}
};
}
var checkKey = createKeyValCheck("key"), checkValue = createKeyValCheck("value");
/**
* @constructor
* @param {string} hash
@@ -167,7 +157,7 @@
Bucket.prototype = {
getEqualityFunction: function (searchValue) {
return (typeof searchValue.equals_za3rmp$ == FUNCTION) ? equals_fixedValueHasEquals : equals_fixedValueNoEquals;
return (searchValue != null && typeof searchValue.equals_za3rmp$ == FUNCTION) ? equals_fixedValueHasEquals : equals_fixedValueNoEquals;
},
getEntryForKey: createBucketSearcher(ENTRY),
@@ -178,7 +168,7 @@
var result = this.getEntryAndIndexForKey(key);
if (result) {
arrayRemoveAt(this.entries, result[0]);
return result[1];
return result;
}
return null;
},
@@ -253,8 +243,6 @@
var equalityFunction = (typeof equalityFunctionParam == FUNCTION) ? equalityFunctionParam : null;
this.put_wn2jw4$ = function (key, value) {
checkKey(key);
checkValue(value);
var hash = hashingFunction(key), bucket, bucketEntry, oldValue = null;
// Check if a bucket exists for the bucket key
@@ -282,8 +270,6 @@
};
this.get_za3rmp$ = function (key) {
checkKey(key);
var hash = hashingFunction(key);
// Check if a bucket exists for the bucket key
@@ -300,7 +286,6 @@
};
this.containsKey_za3rmp$ = function (key) {
checkKey(key);
var bucketKey = hashingFunction(key);
// Check if a bucket exists for the bucket key
@@ -310,7 +295,6 @@
};
this.containsValue_za3rmp$ = function (value) {
checkValue(value);
var i = buckets.length;
while (i--) {
if (buckets[i].containsValue_za3rmp$(value)) {
@@ -354,17 +338,17 @@
};
this.remove_za3rmp$ = function (key) {
checkKey(key);
var hash = hashingFunction(key), bucketIndex, oldValue = null;
var hash = hashingFunction(key), bucketIndex, oldValue = null, result = null;
// Check if a bucket exists for the bucket key
var bucket = getBucketForHash(bucketsByHash, hash);
if (bucket) {
// Remove entry from this bucket for this key
oldValue = bucket.removeEntryForKey(key);
if (oldValue !== null) {
result = bucket.removeEntryForKey(key);
if (result !== null) {
oldValue = result[1];
// Entry was removed, so check if bucket is empty
if (!bucket.entries.length) {
// Bucket is empty, so remove it from the bucket collections
@@ -431,13 +431,6 @@ public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
return filterTo(ArrayList<T>(), predicate)
}
/**
* Returns a list containing all elements matching the given *predicate*
*/
public inline fun <K, V> Map<K, V>.filter(predicate: (Map.Entry<K, V>) -> Boolean): List<Map.Entry<K, V>> {
return filterTo(ArrayList<Map.Entry<K, V>>(), predicate)
}
/**
* Returns a stream containing all elements matching the given *predicate*
*/
@@ -522,13 +515,6 @@ public inline fun <T> Iterable<T>.filterNot(predicate: (T) -> Boolean): List<T>
return filterNotTo(ArrayList<T>(), predicate)
}
/**
* Returns a list containing all elements not matching the given *predicate*
*/
public inline fun <K, V> Map<K, V>.filterNot(predicate: (Map.Entry<K, V>) -> Boolean): List<Map.Entry<K, V>> {
return filterNotTo(ArrayList<Map.Entry<K, V>>(), predicate)
}
/**
* Returns a stream containing all elements not matching the given *predicate*
*/
@@ -668,14 +654,6 @@ public inline fun <T, C : MutableCollection<in T>> Iterable<T>.filterNotTo(desti
return destination
}
/**
* Appends all elements not matching the given *predicate* to the given *destination*
*/
public inline fun <K, V, C : MutableCollection<in Map.Entry<K, V>>> Map<K, V>.filterNotTo(destination: C, predicate: (Map.Entry<K, V>) -> Boolean): C {
for (element in this) if (!predicate(element)) destination.add(element)
return destination
}
/**
* Appends all elements not matching the given *predicate* to the given *destination*
*/
@@ -772,14 +750,6 @@ public inline fun <T, C : MutableCollection<in T>> Iterable<T>.filterTo(destinat
return destination
}
/**
* Appends all elements matching the given *predicate* into the given *destination*
*/
public inline fun <K, V, C : MutableCollection<in Map.Entry<K, V>>> Map<K, V>.filterTo(destination: C, predicate: (Map.Entry<K, V>) -> Boolean): C {
for (element in this) if (predicate(element)) destination.add(element)
return destination
}
/**
* Appends all elements matching the given *predicate* into the given *destination*
*/
+12 -31
View File
@@ -245,91 +245,84 @@ public inline fun <T, R, C : MutableCollection<in R>> Stream<T>.flatMapTo(destin
* Returns a map of the elements in original collection grouped by the result of given *toKey* function
*/
public inline fun <T, K> Array<out T>.groupBy(toKey: (T) -> K): Map<K, List<T>> {
return groupByTo(HashMap<K, MutableList<T>>(), toKey)
return groupByTo(LinkedHashMap<K, MutableList<T>>(), toKey)
}
/**
* Returns a map of the elements in original collection grouped by the result of given *toKey* function
*/
public inline fun <K> BooleanArray.groupBy(toKey: (Boolean) -> K): Map<K, List<Boolean>> {
return groupByTo(HashMap<K, MutableList<Boolean>>(), toKey)
return groupByTo(LinkedHashMap<K, MutableList<Boolean>>(), toKey)
}
/**
* Returns a map of the elements in original collection grouped by the result of given *toKey* function
*/
public inline fun <K> ByteArray.groupBy(toKey: (Byte) -> K): Map<K, List<Byte>> {
return groupByTo(HashMap<K, MutableList<Byte>>(), toKey)
return groupByTo(LinkedHashMap<K, MutableList<Byte>>(), toKey)
}
/**
* Returns a map of the elements in original collection grouped by the result of given *toKey* function
*/
public inline fun <K> CharArray.groupBy(toKey: (Char) -> K): Map<K, List<Char>> {
return groupByTo(HashMap<K, MutableList<Char>>(), toKey)
return groupByTo(LinkedHashMap<K, MutableList<Char>>(), toKey)
}
/**
* Returns a map of the elements in original collection grouped by the result of given *toKey* function
*/
public inline fun <K> DoubleArray.groupBy(toKey: (Double) -> K): Map<K, List<Double>> {
return groupByTo(HashMap<K, MutableList<Double>>(), toKey)
return groupByTo(LinkedHashMap<K, MutableList<Double>>(), toKey)
}
/**
* Returns a map of the elements in original collection grouped by the result of given *toKey* function
*/
public inline fun <K> FloatArray.groupBy(toKey: (Float) -> K): Map<K, List<Float>> {
return groupByTo(HashMap<K, MutableList<Float>>(), toKey)
return groupByTo(LinkedHashMap<K, MutableList<Float>>(), toKey)
}
/**
* Returns a map of the elements in original collection grouped by the result of given *toKey* function
*/
public inline fun <K> IntArray.groupBy(toKey: (Int) -> K): Map<K, List<Int>> {
return groupByTo(HashMap<K, MutableList<Int>>(), toKey)
return groupByTo(LinkedHashMap<K, MutableList<Int>>(), toKey)
}
/**
* Returns a map of the elements in original collection grouped by the result of given *toKey* function
*/
public inline fun <K> LongArray.groupBy(toKey: (Long) -> K): Map<K, List<Long>> {
return groupByTo(HashMap<K, MutableList<Long>>(), toKey)
return groupByTo(LinkedHashMap<K, MutableList<Long>>(), toKey)
}
/**
* Returns a map of the elements in original collection grouped by the result of given *toKey* function
*/
public inline fun <K> ShortArray.groupBy(toKey: (Short) -> K): Map<K, List<Short>> {
return groupByTo(HashMap<K, MutableList<Short>>(), toKey)
return groupByTo(LinkedHashMap<K, MutableList<Short>>(), toKey)
}
/**
* Returns a map of the elements in original collection grouped by the result of given *toKey* function
*/
public inline fun <T, K> Iterable<T>.groupBy(toKey: (T) -> K): Map<K, List<T>> {
return groupByTo(HashMap<K, MutableList<T>>(), toKey)
}
/**
* Returns a map of the elements in original collection grouped by the result of given *toKey* function
*/
public inline fun <V, K> Map<K, V>.groupBy(toKey: (Map.Entry<K, V>) -> K): Map<K, List<Map.Entry<K, V>>> {
return groupByTo(HashMap<K, MutableList<Map.Entry<K, V>>>(), toKey)
return groupByTo(LinkedHashMap<K, MutableList<T>>(), toKey)
}
/**
* Returns a map of the elements in original collection grouped by the result of given *toKey* function
*/
public inline fun <T, K> Stream<T>.groupBy(toKey: (T) -> K): Map<K, List<T>> {
return groupByTo(HashMap<K, MutableList<T>>(), toKey)
return groupByTo(LinkedHashMap<K, MutableList<T>>(), toKey)
}
/**
* Returns a map of the elements in original collection grouped by the result of given *toKey* function
*/
public inline fun <K> String.groupBy(toKey: (Char) -> K): Map<K, List<Char>> {
return groupByTo(HashMap<K, MutableList<Char>>(), toKey)
return groupByTo(LinkedHashMap<K, MutableList<Char>>(), toKey)
}
/**
@@ -452,18 +445,6 @@ public inline fun <T, K> Iterable<T>.groupByTo(map: MutableMap<K, MutableList<T>
return map
}
/**
* Appends elements from original collection grouped by the result of given *toKey* function to the given *map*
*/
public inline fun <V, K> Map<K, V>.groupByTo(map: MutableMap<K, MutableList<Map.Entry<K, V>>>, toKey: (Map.Entry<K, V>) -> K): Map<K, MutableList<Map.Entry<K, V>>> {
for (element in this) {
val key = toKey(element)
val list = map.getOrPut(key) { ArrayList<Map.Entry<K, V>>() }
list.add(element)
}
return map
}
/**
* Appends elements from original collection grouped by the result of given *toKey* function to the given *map*
*/
+135 -3
View File
@@ -400,10 +400,10 @@ public fun String.toLinkedList(): LinkedList<Char> {
/**
* Returns a List containing all key-value pairs
*/
public fun <K, V> Map<K, V>.toList(): List<Map.Entry<K, V>> {
val result = ArrayList<Map.Entry<K, V>>(size)
public fun <K, V> Map<K, V>.toList(): List<Pair<K, V>> {
val result = ArrayList<Pair<K, V>>(size)
for (item in this)
result.add(item)
result.add(item.key to item.value)
return result
}
@@ -507,6 +507,138 @@ public fun String.toList(): List<Char> {
return toCollection(ArrayList<Char>())
}
/**
* Returns Map containing all the values from the given collection indexed by *selector*
*/
public inline fun <T, K> Array<out T>.toMap(selector: (T) -> K): Map<K, T> {
val result = LinkedHashMap<K, T>()
for (element in this) {
result.put(selector(element), element)
}
return result
}
/**
* Returns Map containing all the values from the given collection indexed by *selector*
*/
public inline fun <K> BooleanArray.toMap(selector: (Boolean) -> K): Map<K, Boolean> {
val result = LinkedHashMap<K, Boolean>()
for (element in this) {
result.put(selector(element), element)
}
return result
}
/**
* Returns Map containing all the values from the given collection indexed by *selector*
*/
public inline fun <K> ByteArray.toMap(selector: (Byte) -> K): Map<K, Byte> {
val result = LinkedHashMap<K, Byte>()
for (element in this) {
result.put(selector(element), element)
}
return result
}
/**
* Returns Map containing all the values from the given collection indexed by *selector*
*/
public inline fun <K> CharArray.toMap(selector: (Char) -> K): Map<K, Char> {
val result = LinkedHashMap<K, Char>()
for (element in this) {
result.put(selector(element), element)
}
return result
}
/**
* Returns Map containing all the values from the given collection indexed by *selector*
*/
public inline fun <K> DoubleArray.toMap(selector: (Double) -> K): Map<K, Double> {
val result = LinkedHashMap<K, Double>()
for (element in this) {
result.put(selector(element), element)
}
return result
}
/**
* Returns Map containing all the values from the given collection indexed by *selector*
*/
public inline fun <K> FloatArray.toMap(selector: (Float) -> K): Map<K, Float> {
val result = LinkedHashMap<K, Float>()
for (element in this) {
result.put(selector(element), element)
}
return result
}
/**
* Returns Map containing all the values from the given collection indexed by *selector*
*/
public inline fun <K> IntArray.toMap(selector: (Int) -> K): Map<K, Int> {
val result = LinkedHashMap<K, Int>()
for (element in this) {
result.put(selector(element), element)
}
return result
}
/**
* Returns Map containing all the values from the given collection indexed by *selector*
*/
public inline fun <K> LongArray.toMap(selector: (Long) -> K): Map<K, Long> {
val result = LinkedHashMap<K, Long>()
for (element in this) {
result.put(selector(element), element)
}
return result
}
/**
* Returns Map containing all the values from the given collection indexed by *selector*
*/
public inline fun <K> ShortArray.toMap(selector: (Short) -> K): Map<K, Short> {
val result = LinkedHashMap<K, Short>()
for (element in this) {
result.put(selector(element), element)
}
return result
}
/**
* Returns Map containing all the values from the given collection indexed by *selector*
*/
public inline fun <T, K> Iterable<T>.toMap(selector: (T) -> K): Map<K, T> {
val result = LinkedHashMap<K, T>()
for (element in this) {
result.put(selector(element), element)
}
return result
}
/**
* Returns Map containing all the values from the given collection indexed by *selector*
*/
public inline fun <T, K> Stream<T>.toMap(selector: (T) -> K): Map<K, T> {
val result = LinkedHashMap<K, T>()
for (element in this) {
result.put(selector(element), element)
}
return result
}
/**
* Returns Map containing all the values from the given collection indexed by *selector*
*/
public inline fun <K> String.toMap(selector: (Char) -> K): Map<K, Char> {
val result = LinkedHashMap<K, Char>()
for (element in this) {
result.put(selector(element), element)
}
return result
}
/**
* Returns a Set of all elements
*/
@@ -1,11 +1,11 @@
package kotlin
import java.util.*
import java.util.Enumeration
/**
Helper to make java.util.Enumeration usable in for
*/
public fun <T> java.util.Enumeration<T>.iterator(): Iterator<T> = object: Iterator<T> {
public fun <T> Enumeration<T>.iterator(): Iterator<T> = object: Iterator<T> {
override fun hasNext(): Boolean = hasMoreElements()
public override fun next(): T = nextElement()
@@ -17,7 +17,7 @@ public fun listOf<T>(vararg values: T): List<T> = if (values.size == 0) stdlib_e
public fun listOf<T>(): List<T> = stdlib_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 hashMapOf(*values)
public fun mapOf<K, V>(vararg values: Pair<K, V>): Map<K, V> = if (values.size == 0) stdlib_emptyMap() else linkedMapOf(*values)
/** Returns an empty read-only map */
public fun mapOf<K, V>(): Map<K, V> = stdlib_emptyMap()
@@ -40,6 +40,19 @@ public fun <K, V> hashMapOf(vararg values: Pair<K, V>): HashMap<K, V> {
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 size of the collection */
public val Collection<*>.size: Int
get() = size()
@@ -36,25 +36,6 @@ public fun <K, V> sortedMapOf(vararg values: Pair<K, V>): SortedMap<K, V> {
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)
/**
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>
+135 -51
View File
@@ -1,51 +1,52 @@
package kotlin
import java.util.Collections
import java.util.HashMap
import java.util.*
// Map APIs
/** Returns the size of the map */
public val Map<*,*>.size : Int
get() = size()
public val Map<*, *>.size: Int
get() = size()
/** Returns true if this map is empty */
public val Map<*,*>.empty : Boolean
get() = isEmpty()
/** Provides [] access to maps */
public fun <K, V> MutableMap<K, V>.set(key : K, value : V) : V? = this.put(key, value)
public val Map<*, *>.empty: Boolean
get() = isEmpty()
/** 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 stdlib_emptyMap()
public fun <K,V> Map<K,V>.contains(key : K) : Boolean = containsKey(key)
/** Returns the key of the entry */
public val <K,V> Map.Entry<K,V>.key : K
public val <K, V> Map.Entry<K, V>.key: K
get() = getKey()
/** Returns the value of the entry */
public val <K,V> Map.Entry<K,V>.value : V
public val <K, V> Map.Entry<K, V>.value: V
get() = getValue()
/** Returns the key of the entry */
fun <K,V> Map.Entry<K,V>.component1() : K {
fun <K, V> Map.Entry<K, V>.component1(): K {
return getKey()
}
/** Returns the value of the entry */
fun <K,V> Map.Entry<K,V>.component2() : V {
fun <K, V> Map.Entry<K, V>.component2(): V {
return getValue()
}
/** Converts entry to Pair with key being first component and value being second */
fun <K, V> Map.Entry<K, V>.toPair(): Pair<K, V> {
return Pair(getKey(), getValue())
}
/**
* Returns the value for the given key or returns the result of the defaultValue function if there was no entry for the given key
*
* @includeFunctionBody ../../test/collections/MapTest.kt getOrElse
*/
public inline fun <K,V> Map<K,V>.getOrElse(key: K, defaultValue: ()-> V) : V {
public inline fun <K, V> Map<K, V>.getOrElse(key: K, defaultValue: () -> V): V {
if (this.containsKey(key)) {
return this.get(key) as V
} else {
@@ -58,7 +59,7 @@ 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 {
public inline fun <K, V> MutableMap<K, V>.getOrPut(key: K, defaultValue: () -> V): V {
if (this.containsKey(key)) {
return this.get(key) as V
} else {
@@ -68,63 +69,54 @@ public inline fun <K,V> MutableMap<K,V>.getOrPut(key: K, defaultValue: ()-> V) :
}
}
/**
* Returns an [[Iterator]] over the entries in the [[Map]]
*
* @includeFunctionBody ../../test/collections/MapTest.kt iterateWithProperties
*/
public fun <K,V> Map<K,V>.iterator(): Iterator<Map.Entry<K,V>> {
public fun <K, V> Map<K, V>.iterator(): Iterator<Map.Entry<K, V>> {
val entrySet = this.entrySet()
return entrySet.iterator()
}
/**
* Populates the given *result* [[Map]] with the value returned by applying the *transform* function on each [[Map.Entry]] in this [[Map]]
* Populates the given *destination* [[Map]] with the value returned by applying the *transform* function on each [[Map.Entry]] in this [[Map]]
*/
public inline fun <K,V,R,C: MutableMap<K,R>> Map<K,V>.mapValuesTo(result: C, transform : (Map.Entry<K,V>) -> R) : C {
for (e in this) {
val newValue = transform(e)
result.put(e.key, newValue)
}
return result
public inline fun <K, V, R, C : MutableMap<K, R>> Map<K, V>.mapValuesTo(destination: C, transform: (Map.Entry<K, V>) -> R): C {
for (e in this) {
val newValue = transform(e)
destination.put(e.key, newValue)
}
return destination
}
/**
* Populates the given *destination* [[Map]] with the value returned by applying the *transform* function on each [[Map.Entry]] in this [[Map]]
*/
public inline fun <K, V, R, C : MutableMap<R, V>> Map<K, V>.mapKeysTo(destination: C, transform: (Map.Entry<K, V>) -> R): C {
for (e in this) {
val newKey = transform(e)
destination.put(newKey, e.value)
}
return destination
}
/**
* Puts all the entries into this [[MutableMap]] with the first value in the pair being the key and the second the value
*/
public fun <K,V> MutableMap<K,V>.putAll(vararg values: Pair<K, V>): Unit {
public fun <K, V> MutableMap<K, V>.putAll(vararg values: Pair<K, V>): Unit {
for ((key, value) in values) {
put(key, value)
}
}
/**
* Copies the entries in this [[Map]] to the given mutable *map*
* Puts all the entries into this [[MutableMap]] with the first value in the pair being the key and the second the value
*/
public fun <K,V, C : MutableMap<K, in V>> Map<K,V>.toMap(map: C): C {
map.putAll(this)
return map
}
/**
* Copies the entries from given iterable of pairs to the given mutable *map*
*/
public fun <K,V, C : MutableMap<K, in V>> Iterable<Pair<K,V>>.toMap(map: C): C {
for((key,value) in this) {
if (map.containsKey(key)) {
throw DuplicateKeyException()
}
map.put(key,value)
public fun <K, V> MutableMap<K, V>.putAll(values: Iterable<Pair<K,V>>): Unit {
for ((key, value) in values) {
put(key, value)
}
return map
}
/**
* Creates map from given iterable of pairs
*/
public fun <K,V> Iterable<Pair<K,V>>.toMap() : Map<K,V> {
return toMap(HashMap<K,V>())
}
/**
@@ -132,6 +124,98 @@ public fun <K,V> Iterable<Pair<K,V>>.toMap() : Map<K,V> {
*
* @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(java.util.HashMap<K,R>(this.size), transform)
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)
}
/**
* Returns a new Map containing the results of applying the given *transform* function to each [[Map.Entry]] in this [[Map]]
*
* @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)
}
/**
* Returns a map containing all key-value pairs matching keys with the given *predicate*
*/
public inline fun <K, V> Map<K, V>.filterKeys(predicate: (K) -> Boolean): Map<K, V> {
val result = LinkedHashMap<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 matching values with the given *predicate*
*/
public inline fun <K, V> Map<K, V>.filterValues(predicate: (V) -> Boolean): Map<K, V> {
val result = LinkedHashMap<K, V>()
for (entry in this) {
if (predicate(entry.value)) {
result.put(entry.key, entry.value)
}
}
return result
}
/**
* Appends all elements matching the given *predicate* into the given *destination*
*/
public inline fun <K, V, C : MutableMap<K, V>> Map<K, V>.filterTo(destination: C, predicate: (Map.Entry<K, V>) -> Boolean): C {
for (element in this) {
if (predicate(element)) {
destination.put(element.key, element.value)
}
}
return destination
}
/**
* Returns a map containing all key-value pairs matching the given *predicate*
*/
public inline fun <K, V> Map<K, V>.filter(predicate: (Map.Entry<K, V>) -> Boolean): Map<K, V> {
return filterTo(LinkedHashMap<K, V>(), predicate)
}
/**
* Appends all elements matching the given *predicate* into the given *destination*
*/
public inline fun <K, V, C : MutableMap<K, V>> Map<K, V>.filterNotTo(destination: C, predicate: (Map.Entry<K, V>) -> Boolean): C {
for (element in this) {
if (!predicate(element)) {
destination.put(element.key, element.value)
}
}
return destination
}
/**
* Returns a map containing all key-value pairs matching the given *predicate*
*/
public inline fun <K, V> Map<K, V>.filterNot(predicate: (Map.Entry<K, V>) -> Boolean): Map<K, V> {
return filterNotTo(LinkedHashMap<K, V>(), predicate)
}
/**
* Appends given [pair] to the mutable map.
*/
public fun <K, V> MutableMap<K, V>.plusAssign(pair: Pair<K, V>) {
put(pair.first, pair.second)
}
/**
* Returns a map containing all key-value pairs from the given collection
*/
public fun <K, V> Iterable<Pair<K, V>>.toMap(): Map<K, V> {
val result = LinkedHashMap<K, V>()
for (element in this) {
result.put(element.first, element.second)
}
return result
}
@@ -8,17 +8,21 @@ 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> = toMap(LinkedHashMap<K,V>(size))
public fun <K, V> Map<K, V>.toLinkedMap(): LinkedHashMap<K, V> = LinkedHashMap(this)
/**
* Converts this [[Map]] to a [[SortedMap]] so iteration order will be in key order
*
* @includeFunctionBody ../../test/collections/MapTest.kt toSortedMap
*/
public fun <K,V> Map<K,V>.toSortedMap(): SortedMap<K,V> = toMap(TreeMap<K,V>())
public fun <K, V> Map<K, V>.toSortedMap(): SortedMap<K, V> = TreeMap(this)
/**
* Converts this [[Map]] to a [[SortedMap]] using the given *comparator* so that iteration order will be in the order
@@ -26,8 +30,11 @@ public fun <K,V> Map<K,V>.toSortedMap(): SortedMap<K,V> = toMap(TreeMap<K,V>())
*
* @includeFunctionBody ../../test/collections/MapTest.kt toSortedMapWithComparator
*/
public fun <K,V> Map<K,V>.toSortedMap(comparator: Comparator<K>): SortedMap<K,V> = toMap(TreeMap<K,V>(comparator))
public fun <K, V> Map<K, V>.toSortedMap(comparator: Comparator<K>): SortedMap<K, V> {
val result = TreeMap<K, V>(comparator)
result.putAll(this)
return result
}
/**
* Converts this [[Map]] to a [[Properties]] object
@@ -165,10 +165,17 @@ class CollectionTest {
}
test fun groupBy() {
val words = arrayListOf("a", "ab", "abc", "def", "abcd")
val words = arrayListOf("a", "abc", "ab", "def", "abcd")
val byLength = words.groupBy { it.length }
assertEquals(4, byLength.size())
// verify that order of keys is preserved
val listOfPairs = byLength.toList()
assertEquals(1, listOfPairs[0].first)
assertEquals(3, listOfPairs[1].first)
assertEquals(2, listOfPairs[2].first)
assertEquals(4, listOfPairs[3].first)
val l3 = byLength.getOrElse(3, { ArrayList<String>() })
assertEquals(2, l3.size)
}
@@ -40,4 +40,16 @@ class ListSpecificTest {
assertEquals("bar", data.last)
assertEquals(1, data.lastIndex)
}
Test fun mutableList() {
val items = listOf("beverage", "location", "name")
var list = arrayListOf<String>()
for (item in items) {
list += item
}
assertEquals(3, list.size())
assertEquals("beverage,location,name", list.join(","))
}
}
@@ -0,0 +1,44 @@
package test.collections
import kotlin.test.*
import org.junit.Test as test
class MapJVMTest {
test fun createSortedMap() {
val map = sortedMapOf(Pair("c", 3), Pair("b", 2), Pair("a", 1))
assertEquals(1, map["a"])
assertEquals(2, map["b"])
assertEquals(3, map["c"])
assertEquals(arrayListOf("a", "b", "c"), map.keySet().toList())
}
test fun toSortedMap() {
val map = mapOf(Pair("c", 3), Pair("b", 2), Pair("a", 1))
val sorted = map.toSortedMap()
assertEquals(1, sorted["a"])
assertEquals(2, sorted["b"])
assertEquals(3, sorted["c"])
assertEquals(arrayListOf("a", "b", "c"), sorted.keySet().toList())
}
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)
assertEquals(arrayListOf("c", "bc", "bd", "abc"), sorted.keySet().toList())
assertEquals(1, sorted["abc"])
assertEquals(2, sorted["bc"])
assertEquals(3, sorted["c"])
}
test fun toProperties() {
val map = mapOf("a" to "A", "b" to "B")
val prop = map.toProperties()
assertEquals(2, prop.size)
assertEquals("A", prop.getProperty("a", "fail"))
assertEquals("B", prop.getProperty("b", "fail"))
}
}
+93 -112
View File
@@ -1,68 +1,61 @@
package test.collections
import kotlin.test.*
import java.util.*
import org.junit.Test as test
class MapTest {
test fun getOrElse() {
val data = hashMapOf<String, Int>()
val a = data.getOrElse("foo"){2}
val data = mapOf<String, Int>()
val a = data.getOrElse("foo") { 2 }
assertEquals(2, a)
val b = data.getOrElse("foo"){3}
val b = data.getOrElse("foo") { 3 }
assertEquals(3, b)
assertEquals(0, data.size())
val empty = hashMapOf<String, Int?>()
val c = empty.getOrElse("") {null}
val empty = mapOf<String, Int?>()
val c = empty.getOrElse("") { null }
assertEquals(null, c)
}
test fun getOrPut() {
val data = hashMapOf<String, Int>()
val a = data.getOrPut("foo"){2}
val a = data.getOrPut("foo") { 2 }
assertEquals(2, a)
val b = data.getOrPut("foo"){3}
val b = data.getOrPut("foo") { 3 }
assertEquals(2, b)
assertEquals(1, data.size())
val empty = hashMapOf<String, Int?>()
val c = empty.getOrPut("") {null}
val c = empty.getOrPut("") { null }
assertEquals(null, c)
}
test fun sizeAndEmpty() {
val data = hashMapOf<String, Int>()
assertTrue{ data.empty }
assertTrue { data.empty }
assertEquals(data.size, 0)
}
test fun setViaIndexOperators() {
val map = hashMapOf<String, String>()
assertTrue{ map.empty }
assertTrue { map.empty }
assertEquals(map.size, 0)
map["name"] = "James"
assertTrue{ !map.empty }
assertTrue { !map.empty }
assertEquals(map.size(), 1)
assertEquals("James", map["name"])
}
test fun iterate() {
val map = TreeMap<String, String>()
map["beverage"] = "beer"
map["location"] = "Mells"
map["name"] = "James"
val map = mapOf("beverage" to "beer", "location" to "Mells", "name" to "James")
val list = arrayListOf<String>()
for (e in map) {
println("key = ${e.getKey()}, value = ${e.getValue()}")
list.add(e.getKey())
list.add(e.getValue())
}
@@ -72,14 +65,9 @@ class MapTest {
}
test fun iterateWithProperties() {
val map = TreeMap<String, String>()
map["beverage"] = "beer"
map["location"] = "Mells"
map["name"] = "James"
val map = mapOf("beverage" to "beer", "location" to "Mells", "name" to "James")
val list = arrayListOf<String>()
for (e in map) {
println("key = ${e.key}, value = ${e.value}")
list.add(e.key)
list.add(e.value)
}
@@ -89,14 +77,9 @@ class MapTest {
}
test fun iterateWithExtraction() {
val map = TreeMap<String, String>()
map["beverage"] = "beer"
map["location"] = "Mells"
map["name"] = "James"
val map = mapOf("beverage" to "beer", "location" to "Mells", "name" to "James")
val list = arrayListOf<String>()
for ((key, value) in map) {
println("key = ${key}, value = ${value}")
list.add(key)
list.add(value)
}
@@ -106,38 +89,39 @@ class MapTest {
}
test fun contains() {
val map = hashMapOf("a" to 1, "b" to 2)
assert("a" in map)
assert("c" !in map)
val map = mapOf("a" to 1, "b" to 2)
assertTrue("a" in map)
assertTrue("c" !in map)
}
test fun map() {
val m1 = TreeMap<String, String>()
m1["beverage"] = "beer"
m1["location"] = "Mells"
val m1 = mapOf("beverage" to "beer", "location" to "Mells")
val list = m1.map { it.value + " rocks" }
val list = m1.map{ it.value + " rocks" }
println("Got new list $list")
assertEquals(arrayListOf("beer rocks", "Mells rocks"), list)
}
test fun mapValues() {
val m1 = TreeMap<String, String>()
m1["beverage"] = "beer"
m1["location"] = "Mells"
val m2 = m1.mapValues{ it.value + "2" }
val m1 = mapOf("beverage" to "beer", "location" to "Mells")
val m2 = m1.mapValues { it.value + "2" }
assertEquals("beer2", m2["beverage"])
assertEquals("Mells2", m2["location"])
}
test fun mapKeys() {
val m1 = mapOf("beverage" to "beer", "location" to "Mells")
val m2 = m1.mapKeys { it.key + "2" }
assertEquals("beer", m2["beverage2"])
assertEquals("Mells", m2["location2"])
}
test fun createUsingPairs() {
val map = hashMapOf(Pair("a", 1), Pair("b", 2))
val map = mapOf(Pair("a", 1), Pair("b", 2))
assertEquals(2, map.size)
assertEquals(1, map.get("a"))
assertEquals(2, map.get("b"))
assertEquals(1, map["a"])
assertEquals(2, map["b"])
}
test fun createFromIterable() {
@@ -147,80 +131,77 @@ class MapTest {
assertEquals(2, map.get("b"))
}
test fun createUsingTo() {
val map = hashMapOf("a" to 1, "b" to 2)
test fun createWithSelector() {
val map = listOf("a", "bb", "ccc").toMap { it.length }
assertEquals(3, map.size)
assertEquals("a", map.get(1))
assertEquals("bb", map.get(2))
assertEquals("ccc", map.get(3))
}
test fun createWithSelectorAndOverwrite() {
val map = listOf("aa", "bb", "ccc").toMap { it.length }
assertEquals(2, map.size)
assertEquals(1, map.get("a"))
assertEquals(2, map.get("b"))
assertEquals("bb", map.get(2))
assertEquals("ccc", map.get(3))
}
test fun createUsingTo() {
val map = mapOf("a" to 1, "b" to 2)
assertEquals(2, map.size)
assertEquals(1, map["a"])
assertEquals(2, map["b"])
}
test fun createLinkedMap() {
val map = linkedMapOf(Pair("c", 3), Pair("b", 2), Pair("a", 1))
assertEquals(1, map.get("a"))
assertEquals(2, map.get("b"))
assertEquals(3, map.get("c"))
assertEquals(1, map["a"])
assertEquals(2, map["b"])
assertEquals(3, map["c"])
assertEquals(arrayListOf("c", "b", "a"), map.keySet().toList())
}
test fun createSortedMap() {
val map = sortedMapOf(Pair("c", 3), Pair("b", 2), Pair("a", 1))
assertEquals(1, map.get("a"))
assertEquals(2, map.get("b"))
assertEquals(3, map.get("c"))
assertEquals(arrayListOf("a", "b", "c"), map.keySet().toList())
test fun filter() {
val map = mapOf(Pair("b", 3), Pair("c", 2), Pair("a", 2))
val filteredByKey = map.filter { it.key == "b" }
assertEquals(1, filteredByKey.size)
assertEquals(3, filteredByKey["b"])
val filteredByKey2 = map.filterKeys { it == "b" }
assertEquals(1, filteredByKey2.size)
assertEquals(3, filteredByKey2["b"])
val filteredByValue = map.filter { it.value == 2 }
assertEquals(2, filteredByValue.size)
assertEquals(null, filteredByValue["b"])
assertEquals(2, filteredByValue["c"])
assertEquals(2, filteredByValue["a"])
val filteredByValue2 = map.filterValues { it == 2 }
assertEquals(2, filteredByValue2.size)
assertEquals(null, filteredByValue2["b"])
assertEquals(2, filteredByValue2["c"])
assertEquals(2, filteredByValue2["a"])
}
test fun toSortedMap() {
val map = hashMapOf<String,Int>(Pair("c", 3), Pair("b", 2), Pair("a", 1))
val sorted = map.toSortedMap<String,Int>()
assertEquals(1, sorted.get("a"))
assertEquals(2, sorted.get("b"))
assertEquals(3, sorted.get("c"))
assertEquals(arrayListOf("a", "b", "c"), sorted.keySet().toList())
test fun filterNot() {
val map = mapOf(Pair("b", 3), Pair("c", 2), Pair("a", 2))
val filteredByKey = map.filterNot { it.key == "b" }
assertEquals(2, filteredByKey.size)
assertEquals(null, filteredByKey["b"])
assertEquals(2, filteredByKey["c"])
assertEquals(2, filteredByKey["a"])
val filteredByValue = map.filterNot { it.value == 2 }
assertEquals(1, filteredByValue.size)
assertEquals(3, filteredByValue["b"])
}
test fun toSortedMapWithComparator() {
val map = hashMapOf(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)
assertEquals(arrayListOf("c", "bc", "bd", "abc"), sorted.keySet().toList())
assertEquals(1, sorted.get("abc"))
assertEquals(2, sorted.get("bc"))
assertEquals(3, sorted.get("c"))
test fun plusAssign() {
val extended = hashMapOf(Pair("b", 3))
extended += ("c" to 2)
assertEquals(2, extended.size)
assertEquals(2, extended["c"])
assertEquals(3, extended["b"])
}
/**
TODO
test case for http://youtrack.jetbrains.com/issue/KT-1773
test fun compilerBug() {
val map = TreeMap<String, String>()
map["beverage"] = "beer"
map["location"] = "Mells"
map["name"] = "James"
var list = arrayListOf<String>()
for (e in map) {
println("key = ${e.getKey()}, value = ${e.getValue()}")
list += e.getKey()
list += e.getValue()
}
assertEquals(6, list.size())
assertEquals("beverage,beer,location,Mells,name,James", list.join(","))
println("==== worked! $list")
}
*/
test fun toProperties() {
val map = hashMapOf("a" to "A", "b" to "B")
val prop = map.toProperties()
assertEquals(2, prop.size)
assertEquals("A", prop.getProperty("a", "fail"))
assertEquals("B", prop.getProperty("b", "fail"))
}
}
+30
View File
@@ -23,6 +23,7 @@ class ComplexMapJsTest : MapJsTest() {
override fun <T : kotlin.Comparable<T>> Collection<T>.toNormalizedList(): List<T> = this.toSortedList()
// hashMapOf returns ComlpexHashMap because it is Generic
override fun emptyMutableMap(): MutableMap<String, Int> = hashMapOf()
override fun emptyMutableMapWithNullableKeyValue(): MutableMap<String?, Int?> = hashMapOf()
}
class PrimitiveMapJsTest : MapJsTest() {
@@ -39,6 +40,7 @@ class PrimitiveMapJsTest : MapJsTest() {
override fun <T : kotlin.Comparable<T>> Collection<T>.toNormalizedList(): List<T> = this.toSortedList()
override fun emptyMutableMap(): MutableMap<String, Int> = HashMap()
override fun emptyMutableMapWithNullableKeyValue(): MutableMap<String?, Int?> = HashMap()
}
class LinkedHashMapTest : MapJsTest() {
@@ -55,6 +57,7 @@ class LinkedHashMapTest : MapJsTest() {
override fun <T : kotlin.Comparable<T>> Collection<T>.toNormalizedList(): List<T> = this.toList()
override fun emptyMutableMap(): MutableMap<String, Int> = LinkedHashMap()
override fun emptyMutableMapWithNullableKeyValue(): MutableMap<String?, Int?> = LinkedHashMap()
}
abstract class MapJsTest {
@@ -224,6 +227,31 @@ abstract class MapJsTest {
assertTrue(map.isEmpty())
}
test fun nullAsKey() {
val map = emptyMutableMapWithNullableKeyValue()
assertTrue(map.isEmpty())
map.put(null, 23)
assertFalse(map.isEmpty())
assertTrue(map.containsKey(null))
assertEquals(23, map[null])
assertEquals(23, map.remove(null))
assertTrue(map.isEmpty())
assertEquals(null, map[null])
}
test fun nullAsValue() {
val map = emptyMutableMapWithNullableKeyValue()
val KEY = "Key"
assertTrue(map.isEmpty())
map.put(KEY, null)
assertFalse(map.isEmpty())
assertEquals(null, map[KEY])
assertTrue(map.containsValue(null))
assertEquals(null, map.remove(KEY))
assertTrue(map.isEmpty())
}
/*
TODO fix bug with .set() on Map...
@@ -444,6 +472,8 @@ abstract class MapJsTest {
abstract fun emptyMutableMap(): MutableMap<String, Int>
abstract fun emptyMutableMapWithNullableKeyValue(): MutableMap<String?, Int?>
fun createTestMap(): Map<String, Int> = createTestMutableMap()
fun createTestMutableMap(): MutableMap<String, Int> {
+18 -5
View File
@@ -22,10 +22,13 @@ class ComplexSetJsTest : SetJsTest() {
}
// hashSetOf returns ComlpexHashSet because it is Generic
override fun createEmptyMutableSet(): MutableSet<String> = hashSetOf<String>()
override fun createEmptyMutableSet(): MutableSet<String> = hashSetOf()
override fun createEmptyMutableSetWithNullableValues(): MutableSet<String?> = hashSetOf()
}
class PrimitiveSetJsTest : SetJsTest() {
override fun createEmptyMutableSet(): MutableSet<String> = HashSet()
override fun createEmptyMutableSetWithNullableValues(): MutableSet<String?> = HashSet()
test override fun constructors() {
HashSet<String>()
HashSet<String>(3)
@@ -35,11 +38,11 @@ class PrimitiveSetJsTest : SetJsTest() {
assertEquals(data, set)
}
override fun createEmptyMutableSet(): MutableSet<String> = HashSet<String>()
}
class LinkedHashSetTest : SetJsTest() {
override fun createEmptyMutableSet(): MutableSet<String> = LinkedHashSet()
override fun createEmptyMutableSetWithNullableValues(): MutableSet<String?> = LinkedHashSet()
test override fun constructors() {
LinkedHashSet<String>()
LinkedHashSet<String>(3)
@@ -49,8 +52,6 @@ class LinkedHashSetTest : SetJsTest() {
assertEquals(data, set)
}
override fun createEmptyMutableSet(): MutableSet<String> = LinkedHashSet<String>()
}
abstract class SetJsTest {
@@ -187,8 +188,20 @@ abstract class SetJsTest {
test abstract fun constructors()
Test fun nullAsValue() {
val set = createEmptyMutableSetWithNullableValues()
assertTrue(set.isEmpty(), "Set should be empty")
set.add(null)
assertFalse(set.isEmpty(), "Set should not be empty")
assertTrue(set.contains(null), "Set should contains null")
assertTrue(set.remove(null), "Expected true when remove null")
assertTrue(set.isEmpty(), "Set should be empty")
}
//Helpers
abstract fun createEmptyMutableSet(): MutableSet<String>
abstract fun createEmptyMutableSetWithNullableValues(): MutableSet<String?>
fun createTestMutableSet(): MutableSet<String> {
val set = createEmptyMutableSet()
@@ -205,7 +205,6 @@ fun filtering(): List<GenericFunction> {
return FilteringStream(this, true, predicate)
"""
}
include(Maps)
}
templates add f("filterTo(destination: C, predicate: (T) -> Boolean)") {
@@ -232,8 +231,6 @@ fun filtering(): List<GenericFunction> {
return destination
"""
}
include(Maps)
}
templates add f("filterNot(predicate: (T) -> Boolean)") {
@@ -262,7 +259,6 @@ fun filtering(): List<GenericFunction> {
return FilteringStream(this, false, predicate)
"""
}
include(Maps)
}
templates add f("filterNotTo(destination: C, predicate: (T) -> Boolean)") {
@@ -286,7 +282,6 @@ fun filtering(): List<GenericFunction> {
return destination
"""
}
include(Maps)
}
templates add f("filterNotNull()") {
@@ -184,8 +184,7 @@ fun mapping(): List<GenericFunction> {
doc { "Returns a map of the elements in original collection grouped by the result of given *toKey* function" }
typeParam("K")
returns("Map<K, List<T>>")
body { "return groupByTo(HashMap<K, MutableList<T>>(), toKey)" }
include(Maps)
body { "return groupByTo(LinkedHashMap<K, MutableList<T>>(), toKey)" }
}
templates add f("groupByTo(map: MutableMap<K, MutableList<T>>, toKey: (T) -> K)") {
@@ -204,7 +203,6 @@ fun mapping(): List<GenericFunction> {
return map
"""
}
include(Maps)
}
return templates
}
@@ -62,12 +62,12 @@ fun snapshots(): List<GenericFunction> {
templates add f("toList()") {
only(Maps)
doc { "Returns a List containing all key-value pairs" }
returns("List<Map.Entry<K, V>>")
returns("List<Pair<K, V>>")
body {
"""
val result = ArrayList<Map.Entry<K, V>>(size)
val result = ArrayList<Pair<K, V>>(size)
for (item in this)
result.add(item)
result.add(item.key to item.value)
return result
"""
}
@@ -106,5 +106,25 @@ fun snapshots(): List<GenericFunction> {
body { "return toCollection(LinkedList<T>())" }
}
templates add f("toMap(selector: (T) -> K)") {
inline(true)
typeParam("K")
doc {
"""
Returns Map containing all the values from the given collection indexed by *selector*
"""
}
returns("Map<K, T>")
body {
"""
val result = LinkedHashMap<K, T>()
for (element in this) {
result.put(selector(element), element)
}
return result
"""
}
}
return templates
}