Merge pull request #495 from JetBrains/rr/stdlib_maps
Map-related fixes and improvements in stdlib.
This commit is contained in:
@@ -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)) {
|
||||
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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");
|
||||
}
|
||||
+1
-1
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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*
|
||||
*/
|
||||
|
||||
@@ -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*
|
||||
*/
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"))
|
||||
}
|
||||
}
|
||||
@@ -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"))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user