Flatten HashMap hierarhy, provide string-keyed map and set specializations.

This commit is contained in:
Ilya Gorbunov
2016-08-26 21:51:37 +03:00
parent 5833d32f25
commit e342593d2e
11 changed files with 426 additions and 352 deletions
@@ -1,264 +0,0 @@
/*
* Copyright 2010-2016 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.
*/
/*
* Based on GWT AbstractHashMap
* Copyright 2008 Google Inc.
*/
package kotlin.collections
import kotlin.collections.Map.Entry
import kotlin.collections.MutableMap.MutableEntry
abstract class AbstractHashMap<K, V> : AbstractMap<K, V> {
private inner class EntrySet : AbstractSet<MutableEntry<K, V>>() {
override fun clear() {
this@AbstractHashMap.clear()
}
override operator fun contains(element: MutableEntry<K, V>): Boolean = containsEntry(element)
override operator fun iterator(): MutableIterator<MutableEntry<K, V>> = hashCodeMap.iterator()
override fun remove(entry: MutableEntry<K, V>): Boolean {
if (contains(entry)) {
this@AbstractHashMap.remove(entry.key)
return true
}
return false
}
override val size: Int get() = this@AbstractHashMap.size
}
/*
private inner class EntrySetIterator : Iterator<Entry<K, V>> {
private val stringMapEntries = stringMap!!.iterator()
private var current: MutableIterator<Entry<K, V>> = stringMapEntries
private var last: MutableIterator<Entry<K, V>>? = null
private var hasNext = computeHasNext()
init {
recordLastKnownStructure(this@AbstractHashMap, this)
}
override fun hasNext(): Boolean {
return hasNext
}
private fun computeHasNext(): Boolean {
if (current.hasNext()) {
return true
}
if (current !== stringMapEntries) {
return false
}
current = hashCodeMap!!.iterator()
return current.hasNext()
}
override fun next(): Entry<K, V> {
checkStructuralChange(this@AbstractHashMap, this)
checkElement(hasNext())
last = current
val rv = current.next()
hasNext = computeHasNext()
return rv
}
override fun remove() {
checkState(last != null)
checkStructuralChange(this@AbstractHashMap, this)
last!!.remove()
last = null
hasNext = computeHasNext()
recordLastKnownStructure(this@AbstractHashMap, this)
}
}*/
/**
* A map of integral hashCodes onto entries.
*/
private var hashCodeMap = InternalHashCodeMap<K, V>(this)
// /**
// * A map of Strings onto values.
// */
// @Transient private var stringMap: InternalStringMap<K, V>? = null
constructor() : super()
// init {
// reset()
// }
constructor(capacity: Int, loadFactor: Float = 0f) : this() {
// This implementation of HashMap has no need of load factors or capacities.
require(capacity >= 0) { "Negative initial capacity" }
require(loadFactor >= 0) { "Non-positive load factor" }
}
constructor(original: Map<out K, V>) : this() {
this.putAll(original)
}
override fun clear() {
// reset()
// }
//
// private fun reset() {
hashCodeMap = InternalHashCodeMap<K, V>(this)
// stringMap = InternalStringMap<K, V>(this)
// structureChanged(this)
}
// @SpecializeMethod(params = { String.class }, target = "hasStringValue")
override fun containsKey(key: K): Boolean {
return hasHashValue(key)
// return if (key is String)
// hasStringValue(JsUtils.unsafeCastToString(key))
// else
// hasHashValue(key)
}
override fun containsValue(value: V): Boolean {
return /*containsValue(value, stringMap) || */ containsValue(value, hashCodeMap)
}
private fun containsValue(value: V, entries: Iterable<Entry<K, V>>): Boolean = entries.any { equals(it.value, value) }
override val entries: MutableSet<MutableMap.MutableEntry<K, V>>
get() = EntrySet()
// @SpecializeMethod(params = { String.class }, target = "getStringValue")
override operator fun get(key: K): V? {
return getHashValue(key)
// return if (key is String)
// getStringValue(JsUtils.unsafeCastToString(key))
// else
// getHashValue(key)
}
// @SpecializeMethod(params = { String.class, Object .class }, target = "putStringValue")
override fun put(key: K, value: V): V? {
return putHashValue(key, value)
// return if (key is String)
// putStringValue(JsUtils.unsafeCastToString(key), value)
// else
// putHashValue(key, value)
}
// @SpecializeMethod(params = { String.class }, target = "removeStringValue")
override fun remove(key: K): V? {
return removeHashValue(key)
// return if (key is String)
// removeStringValue(JsUtils.unsafeCastToString(key))
// else
// removeHashValue(key)
}
override val size: Int get() {
return hashCodeMap.size /*+ stringMap!!.size()*/
}
/**
* Subclasses must override to return a whether or not two keys or values are
* equal.
*/
internal abstract fun equals(value1: Any?, value2: Any?): Boolean
/**
* Subclasses must override to return a hash code for a given key. The key is
* guaranteed to be non-null and not a String.
*/
internal abstract fun getHashCode(key: K): Int
/**
* Returns the Map.Entry whose key is Object equal to `key`,
* provided that `key`'s hash code is `hashCode`;
* or `null` if no such Map.Entry exists at the specified
* hashCode.
*/
private fun getHashValue(key: K): V? {
return hashCodeMap.getEntry(key)?.value
}
// /**
// * Returns the value for the given key in the stringMap. Returns
// * `null` if the specified key does not exist.
// */
// private fun getStringValue(key: String?): V {
// return if (key == null) getHashValue(null) else stringMap!!.get(key)
// }
/**
* Returns true if the a key exists in the hashCodeMap that is Object equal to
* `key`, provided that `key`'s hash code is
* `hashCode`.
*/
private fun hasHashValue(key: K): Boolean {
return hashCodeMap.getEntry(key) != null
}
//
// /**
// * Returns true if the given key exists in the stringMap.
// */
// private fun hasStringValue(key: String?): Boolean {
// return if (key == null) hasHashValue(null) else stringMap!!.contains(key)
// }
/**
* Sets the specified key to the specified value in the hashCodeMap. Returns
* the value previously at that key. Returns `null` if the
* specified key did not exist.
*/
private fun putHashValue(key: K, value: V): V? {
return hashCodeMap.put(key, value)
}
// /**
// * Sets the specified key to the specified value in the stringMap. Returns the
// * value previously at that key. Returns `null` if the specified
// * key did not exist.
// */
// private fun putStringValue(key: String?, value: V): V {
// return if (key == null) putHashValue(null, value) else stringMap!!.put(key, value)
// }
/**
* Removes the pair whose key is Object equal to `key` from
* `hashCodeMap`, provided that `key`'s hash code
* is `hashCode`. Returns the value that was associated with the
* removed key, or null if no such key existed.
*/
private fun removeHashValue(key: K): V? {
return hashCodeMap.remove(key)
}
// /**
// * Removes the specified key from the stringMap and returns the value that was
// * previously there. Returns `null` if the specified key does not
// * exist.
// */
// private fun removeStringValue(key: String?): V {
// return if (key == null) removeHashValue(null) else stringMap!!.remove(key)
// }
}
@@ -0,0 +1,38 @@
/*
* Copyright 2010-2016 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 kotlin.collections
internal interface EqualityComparator {
/**
* Subclasses must override to return a whether or not two keys or values are
* equal.
*/
abstract fun equals(value1: Any?, value2: Any?): Boolean
/**
* Subclasses must override to return a hash code for a given key. The key is
* guaranteed to be non-null and not a String.
*/
abstract fun getHashCode(value: Any?): Int
object HashCode : EqualityComparator {
override fun equals(value1: Any?, value2: Any?): Boolean = value1 == value2
override fun getHashCode(value: Any?): Int = value?.hashCode() ?: 0
}
}
+249 -9
View File
@@ -14,24 +14,264 @@
* limitations under the License.
*/
/*
* Based on GWT HashMap
* Based on GWT AbstractHashMap
* Copyright 2008 Google Inc.
*/
package kotlin.collections
import kotlin.collections.Map.Entry
import kotlin.collections.MutableMap.MutableEntry
open class HashMap<K, V> : AbstractHashMap<K, V> {
open class HashMap<K, V> : AbstractMap<K, V> {
constructor() : super()
constructor(capacity: Int, loadFactor: Float = 0f) : super(capacity, loadFactor)
constructor(original: Map<out K, V>) : super(original)
private inner class EntrySet : AbstractSet<MutableEntry<K, V>>() {
// public override fun clone(): Any {
// return HashMap<K, V>(this)
override fun clear() {
this@HashMap.clear()
}
override operator fun contains(element: MutableEntry<K, V>): Boolean = containsEntry(element)
override operator fun iterator(): MutableIterator<MutableEntry<K, V>> = internalMap.iterator()
override fun remove(entry: MutableEntry<K, V>): Boolean {
if (contains(entry)) {
this@HashMap.remove(entry.key)
return true
}
return false
}
override val size: Int get() = this@HashMap.size
}
/*
private inner class EntrySetIterator : Iterator<Entry<K, V>> {
private val stringMapEntries = stringMap!!.iterator()
private var current: MutableIterator<Entry<K, V>> = stringMapEntries
private var last: MutableIterator<Entry<K, V>>? = null
private var hasNext = computeHasNext()
init {
recordLastKnownStructure(this@AbstractHashMap, this)
}
override fun hasNext(): Boolean {
return hasNext
}
private fun computeHasNext(): Boolean {
if (current.hasNext()) {
return true
}
if (current !== stringMapEntries) {
return false
}
current = hashCodeMap!!.iterator()
return current.hasNext()
}
override fun next(): Entry<K, V> {
checkStructuralChange(this@AbstractHashMap, this)
checkElement(hasNext())
last = current
val rv = current.next()
hasNext = computeHasNext()
return rv
}
override fun remove() {
checkState(last != null)
checkStructuralChange(this@AbstractHashMap, this)
last!!.remove()
last = null
hasNext = computeHasNext()
recordLastKnownStructure(this@AbstractHashMap, this)
}
}*/
/**
* A map of integral hashCodes onto entries.
*/
private val internalMap: InternalMap<K, V>
internal val equality: EqualityComparator
// /**
// * A map of Strings onto values.
// */
// @Transient private var stringMap: InternalStringMap<K, V>? = null
//
internal constructor(internalMapProvider: (HashMap<K, V>) -> InternalMap<K, V>, equality: EqualityComparator = EqualityComparator.HashCode) : super() {
this.equality = equality
this.internalMap = internalMapProvider(this)
}
constructor() : this( { m -> InternalHashCodeMap(m) })
// init {
// reset()
// }
override fun equals(value1: Any?, value2: Any?): Boolean = value1 == value2
constructor(capacity: Int, loadFactor: Float = 0f) : this() {
// This implementation of HashMap has no need of load factors or capacities.
require(capacity >= 0) { "Negative initial capacity" }
require(loadFactor >= 0) { "Non-positive load factor" }
}
override fun getHashCode(key: K): Int = key?.hashCode() ?: 0
constructor(original: Map<out K, V>) : this() {
this.putAll(original)
}
override fun clear() {
internalMap.clear()
// reset()
// }
//
// private fun reset() {
// internalMap = internalMapProvider(this)
// stringMap = InternalStringMap<K, V>(this)
// structureChanged(this)
}
// @SpecializeMethod(params = { String.class }, target = "hasStringValue")
override fun containsKey(key: K): Boolean {
return internalMap.contains(key)
// return if (key is String)
// hasStringValue(JsUtils.unsafeCastToString(key))
// else
// hasHashValue(key)
}
override fun containsValue(value: V): Boolean {
return /*containsValue(value, stringMap) || */ containsValue(value, internalMap)
}
private fun containsValue(value: V, entries: Iterable<Entry<K, V>>): Boolean = entries.any { equality.equals(it.value, value) }
override val entries: MutableSet<MutableMap.MutableEntry<K, V>>
get() = EntrySet()
// @SpecializeMethod(params = { String.class }, target = "getStringValue")
override operator fun get(key: K): V? {
return internalMap.get(key)
// return if (key is String)
// getStringValue(JsUtils.unsafeCastToString(key))
// else
// getHashValue(key)
}
// @SpecializeMethod(params = { String.class, Object .class }, target = "putStringValue")
override fun put(key: K, value: V): V? {
return internalMap.put(key, value)
// return if (key is String)
// putStringValue(JsUtils.unsafeCastToString(key), value)
// else
// putHashValue(key, value)
}
// @SpecializeMethod(params = { String.class }, target = "removeStringValue")
override fun remove(key: K): V? {
return internalMap.remove(key)
// return if (key is String)
// removeStringValue(JsUtils.unsafeCastToString(key))
// else
// removeHashValue(key)
}
override val size: Int get() {
return internalMap.size /*+ stringMap!!.size()*/
}
// /**
// * Subclasses must override to return a whether or not two keys or values are
// * equal.
// */
// internal abstract fun equals(value1: Any?, value2: Any?): Boolean
//
// /**
// * Subclasses must override to return a hash code for a given key. The key is
// * guaranteed to be non-null and not a String.
// */
// internal abstract fun getHashCode(key: K): Int
//
// /**
// * Returns the Map.Entry whose key is Object equal to `key`,
// * provided that `key`'s hash code is `hashCode`;
// * or `null` if no such Map.Entry exists at the specified
// * hashCode.
// */
// private fun getHashValue(key: K): V? {
// return hashCodeMap.getEntry(key)?.value
// }
// /**
// * Returns the value for the given key in the stringMap. Returns
// * `null` if the specified key does not exist.
// */
// private fun getStringValue(key: String?): V {
// return if (key == null) getHashValue(null) else stringMap!!.get(key)
// }
// /**
// * Returns true if the a key exists in the hashCodeMap that is Object equal to
// * `key`, provided that `key`'s hash code is
// * `hashCode`.
// */
// private fun hasHashValue(key: K): Boolean {
// return hashCodeMap.getEntry(key) != null
// }
//
// /**
// * Returns true if the given key exists in the stringMap.
// */
// private fun hasStringValue(key: String?): Boolean {
// return if (key == null) hasHashValue(null) else stringMap!!.contains(key)
// }
// /**
// * Sets the specified key to the specified value in the hashCodeMap. Returns
// * the value previously at that key. Returns `null` if the
// * specified key did not exist.
// */
// private fun putHashValue(key: K, value: V): V? {
// return hashCodeMap.put(key, value)
// }
// /**
// * Sets the specified key to the specified value in the stringMap. Returns the
// * value previously at that key. Returns `null` if the specified
// * key did not exist.
// */
// private fun putStringValue(key: String?, value: V): V {
// return if (key == null) putHashValue(null, value) else stringMap!!.put(key, value)
// }
// /**
// * Removes the pair whose key is Object equal to `key` from
// * `hashCodeMap`, provided that `key`'s hash code
// * is `hashCode`. Returns the value that was associated with the
// * removed key, or null if no such key existed.
// */
// private fun removeHashValue(key: K): V? {
// return hashCodeMap.remove(key)
// }
// /**
// * Removes the specified key from the stringMap and returns the value that was
// * previously there. Returns `null` if the specified key does not
// * exist.
// */
// private fun removeStringValue(key: String?): V {
// return if (key == null) removeHashValue(null) else stringMap!!.remove(key)
// }
}
public fun <V> stringMapOf(vararg pairs: Pair<String, V>): HashMap<String, V> {
return HashMap<String, V>({ m -> InternalStringMap(m) }).apply { putAll(pairs) }
}
@@ -44,7 +44,7 @@ open class HashSet<E> : AbstractSet<E> {
* @param map underlying map to use.
*/
protected constructor(map: HashMap<E, Any>) {
internal constructor(map: HashMap<E, Any>) {
this.map = map
}
@@ -72,3 +72,7 @@ open class HashSet<E> : AbstractSet<E> {
override val size: Int get() = map.size
}
public fun stringSetOf(vararg elements: String): HashSet<String> {
return HashSet(stringMapOf<Any>()).apply { addAll(elements) }
}
@@ -35,14 +35,14 @@ import kotlin.collections.AbstractMap.SimpleEntry
* have the same hash, each value in hashCodeMap is actually an array containing all entries whose
* keys share the same hash.
*/
internal class InternalHashCodeMap<K, V>(private val host: AbstractHashMap<K, V>) : MutableIterable<MutableEntry<K, V>> {
internal class InternalHashCodeMap<K, V>(private val host: HashMap<K, V>) : InternalMap<K, V> {
private val backingMap: dynamic = js("new Object()")
var size: Int = 0
private var backingMap: dynamic = js("Object.create(null)")
override var size: Int = 0
private set
fun put(key: K, value: V): V? {
val hashCode = host.getHashCode(key)
override fun put(key: K, value: V): V? {
val hashCode = host.equality.getHashCode(key)
val chain = getChainOrNull(hashCode)
if (chain == null) {
// This is a new chain, put it to the map.
@@ -61,12 +61,12 @@ internal class InternalHashCodeMap<K, V>(private val host: AbstractHashMap<K, V>
return null
}
fun remove(key: K): V? {
val hashCode = host.getHashCode(key)
override fun remove(key: K): V? {
val hashCode = host.equality.getHashCode(key)
val chain = getChainOrNull(hashCode) ?: return null
for (index in 0..chain.size-1) {
val entry = chain[index]
if (host.equals(key, entry.key)) {
if (host.equality.equals(key, entry.key)) {
if (chain.size == 1) {
chain.asDynamic().length = 0
// remove the whole array
@@ -84,11 +84,20 @@ internal class InternalHashCodeMap<K, V>(private val host: AbstractHashMap<K, V>
return null
}
fun getEntry(key: K): MutableEntry<K, V>? =
getChainOrNull(host.getHashCode(key))?.findEntryInChain(key)
override fun clear() {
backingMap = js("Object.create(null)")
size = 0
}
override fun contains(key: K): Boolean = getEntry(key) != null
override fun get(key: K): V? = getEntry(key)?.value
private fun getEntry(key: K): MutableEntry<K, V>? =
getChainOrNull(host.equality.getHashCode(key))?.findEntryInChain(key)
private fun Array<MutableEntry<K, V>>.findEntryInChain(key: K): MutableEntry<K, V>? =
firstOrNull { entry -> host.equals(entry.key, key) }
firstOrNull { entry -> host.equality.equals(entry.key, key) }
override fun iterator(): MutableIterator<MutableEntry<K, V>> {
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2016 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 kotlin.collections
internal interface InternalMap<K, V> : MutableIterable<MutableMap.MutableEntry<K, V>> {
val size: Int
operator fun contains(key: K): Boolean
operator fun get(key: K): V?
fun put(key: K, value: V): V?
fun remove(key: K): V?
fun clear(): Unit
}
@@ -19,106 +19,103 @@
*/
package kotlin.collections
import kotlin.collections.MutableMap.MutableEntry
/**
* A simple wrapper around JavaScript Map for key type is string.
*/
internal class InternalStringMap<K, V>(private val host: AbstractHashMap<K, V>) : Iterable<Entry<K, V>> {
internal class InternalStringMap<K, V>(private val host: HashMap<K, V>) : InternalMap<K, V> {
private val backingMap = InternalJsMapFactory.newJsMap()
private var size: Int = 0
private var backingMap: dynamic = js("Object.create(null)")
override var size: Int = 0
private set
/**
* A mod count to track 'value' replacements in map to ensure that the 'value' that we have in the
* iterator entry is guaranteed to be still correct.
* This is to optimize for the common scenario where the values are not modified during
* iterations where the entries are never stale.
*/
private var valueMod: Int = 0
// /**
// * A mod count to track 'value' replacements in map to ensure that the 'value' that we have in the
// * iterator entry is guaranteed to be still correct.
// * This is to optimize for the common scenario where the values are not modified during
// * iterations where the entries are never stale.
// */
// private var valueMod: Int = 0
operator fun contains(key: String): Boolean {
return !JsUtils.isUndefined(backingMap.get(key))
override operator fun contains(key: K): Boolean {
if (key !is String) return false
return backingMap[key] !== undefined
}
operator fun get(key: String): V {
return backingMap.get(key)
override operator fun get(key: K): V? {
if (key !is String) return null
val value = backingMap[key]
return if (value !== undefined) value as V else null
}
fun put(key: String, value: V): V {
val oldValue = backingMap.get(key)
backingMap.set(key, toNullIfUndefined(value))
if (JsUtils.isUndefined(oldValue)) {
override fun put(key: K, value: V): V? {
require(key is String)
val oldValue = backingMap[key]
backingMap[key] = value
if (oldValue == undefined) {
size++
structureChanged(host)
// structureChanged(host)
return null
}
else {
valueMod++
// valueMod++
return oldValue as V
}
return oldValue
}
fun remove(key: String): V {
val value = backingMap.get(key)
if (!JsUtils.isUndefined(value)) {
backingMap.delete(key)
override fun remove(key: K): V? {
if (key !is String) return null
val value = backingMap[key]
if (value !== undefined) {
deleteProperty(backingMap, key!!)
size--
structureChanged(host)
// structureChanged(host)
return value as V
}
else {
valueMod++
// valueMod++
return null
}
return value
}
fun size(): Int {
return size
override fun clear() {
backingMap = js("Object.create(null)")
size = 0
}
override fun iterator(): Iterator<Entry<K, V>> {
return object : Iterator<Entry<K, V>> {
internal var entries = backingMap.entries()
internal var current = entries.next()
internal var last: InternalJsMap.IteratorEntry<V>
override fun hasNext(): Boolean {
return !current.done
}
override fun iterator(): MutableIterator<MutableEntry<K, V>> {
return object : MutableIterator<MutableEntry<K, V>> {
private val keys: Array<String> = js("Object").keys(backingMap)
private val iterator = keys.iterator()
private var lastKey: String? = null
override fun next(): Entry<K, V> {
last = current
current = entries.next()
return newMapEntry(last, valueMod)
override fun hasNext(): Boolean = iterator.hasNext()
override fun next(): MutableEntry<K, V> {
val key = iterator.next()
lastKey = key
return newMapEntry(key as K)
}
override fun remove() {
this@InternalStringMap.remove(last.getKey())
this@InternalStringMap.remove(checkNotNull(lastKey) as K)
}
}
}
private fun newMapEntry(entry: InternalJsMap.IteratorEntry<V>,
lastValueMod: Int): Entry<K, V> {
return object : AbstractMapEntry<K, V>() {
val key: K
@SuppressWarnings("unchecked")
get() = entry.getKey()
// Let's get a fresh copy as the value may have changed.
val value: V
get() {
if (valueMod != lastValueMod) {
return get(entry.getKey())
}
return entry.getValue()
}
private fun newMapEntry(key: K): MutableEntry<K, V> = object : MutableEntry<K, V> {
override val key: K get() = key
override val value: V get() = this@InternalStringMap[key] as V
fun setValue(`object`: V): V {
return put(entry.getKey(), `object`)
}
}
}
override fun setValue(value: V): V = this@InternalStringMap.put(key, value) as V
private fun <T> toNullIfUndefined(value: T): T? {
return if (JsUtils.isUndefined(value)) null else value
override fun hashCode(): Int = AbstractMap.entryHashCode(this)
override fun toString(): String = AbstractMap.entryToString(this)
override fun equals(other: Any?): Boolean = AbstractMap.entryEquals(this, other)
}
}
+1 -1
View File
@@ -41,7 +41,7 @@ class PrimitiveMapJsTest : MapJsTest() {
}
override fun <T : kotlin.Comparable<T>> Collection<T>.toNormalizedList(): List<T> = this.sorted()
override fun emptyMutableMap(): MutableMap<String, Int> = HashMap()
override fun emptyMutableMap(): MutableMap<String, Int> = stringMapOf()
override fun emptyMutableMapWithNullableKeyValue(): MutableMap<String?, Int?> = HashMap()
@test fun compareBehavior() {
+1 -1
View File
@@ -31,7 +31,7 @@ class ComplexSetJsTest : SetJsTest() {
}
class PrimitiveSetJsTest : SetJsTest() {
override fun createEmptyMutableSet(): MutableSet<String> = HashSet()
override fun createEmptyMutableSet(): MutableSet<String> = stringSetOf()
override fun createEmptyMutableSetWithNullableValues(): MutableSet<String?> = HashSet()
@Test
override fun constructors() {
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright 2010-2016 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 test.collections.js
import java.util.*
public fun <V> stringMapOf(vararg pairs: Pair<String, V>): HashMap<String, V> = hashMapOf<String, V>(*pairs)
public fun stringSetOf(vararg elements: String): HashSet<String> = hashSetOf(*elements)
+1
View File
@@ -43,6 +43,7 @@
<!-- exclude JVM tests-->
<exclude name="**/*JVM.kt"/>
<exclude name="**/*JVMTest.kt"/>
<exclude name="**/*JVMTests.kt"/>