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. * limitations under the License.
*/ */
/* /*
* Based on GWT HashMap * Based on GWT AbstractHashMap
* Copyright 2008 Google Inc. * Copyright 2008 Google Inc.
*/ */
package kotlin.collections 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() private inner class EntrySet : AbstractSet<MutableEntry<K, V>>() {
constructor(capacity: Int, loadFactor: Float = 0f) : super(capacity, loadFactor)
constructor(original: Map<out K, V>) : super(original)
// public override fun clone(): Any { override fun clear() {
// return HashMap<K, V>(this) 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. * @param map underlying map to use.
*/ */
protected constructor(map: HashMap<E, Any>) { internal constructor(map: HashMap<E, Any>) {
this.map = map this.map = map
} }
@@ -72,3 +72,7 @@ open class HashSet<E> : AbstractSet<E> {
override val size: Int get() = map.size 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 * have the same hash, each value in hashCodeMap is actually an array containing all entries whose
* keys share the same hash. * 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()") private var backingMap: dynamic = js("Object.create(null)")
var size: Int = 0 override var size: Int = 0
private set private set
fun put(key: K, value: V): V? { override fun put(key: K, value: V): V? {
val hashCode = host.getHashCode(key) val hashCode = host.equality.getHashCode(key)
val chain = getChainOrNull(hashCode) val chain = getChainOrNull(hashCode)
if (chain == null) { if (chain == null) {
// This is a new chain, put it to the map. // 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 return null
} }
fun remove(key: K): V? { override fun remove(key: K): V? {
val hashCode = host.getHashCode(key) val hashCode = host.equality.getHashCode(key)
val chain = getChainOrNull(hashCode) ?: return null val chain = getChainOrNull(hashCode) ?: return null
for (index in 0..chain.size-1) { for (index in 0..chain.size-1) {
val entry = chain[index] val entry = chain[index]
if (host.equals(key, entry.key)) { if (host.equality.equals(key, entry.key)) {
if (chain.size == 1) { if (chain.size == 1) {
chain.asDynamic().length = 0 chain.asDynamic().length = 0
// remove the whole array // remove the whole array
@@ -84,11 +84,20 @@ internal class InternalHashCodeMap<K, V>(private val host: AbstractHashMap<K, V>
return null return null
} }
fun getEntry(key: K): MutableEntry<K, V>? = override fun clear() {
getChainOrNull(host.getHashCode(key))?.findEntryInChain(key) 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>? = 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>> { 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 package kotlin.collections
import kotlin.collections.MutableMap.MutableEntry
/** /**
* A simple wrapper around JavaScript Map for key type is string. * 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 backingMap: dynamic = js("Object.create(null)")
private var size: Int = 0 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 // * 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. // * iterator entry is guaranteed to be still correct.
* This is to optimize for the common scenario where the values are not modified during // * This is to optimize for the common scenario where the values are not modified during
* iterations where the entries are never stale. // * iterations where the entries are never stale.
*/ // */
private var valueMod: Int = 0 // private var valueMod: Int = 0
operator fun contains(key: String): Boolean { override operator fun contains(key: K): Boolean {
return !JsUtils.isUndefined(backingMap.get(key)) if (key !is String) return false
return backingMap[key] !== undefined
} }
operator fun get(key: String): V { override operator fun get(key: K): V? {
return backingMap.get(key) 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++ size++
structureChanged(host) // structureChanged(host)
return null
} }
else { else {
valueMod++ // valueMod++
return oldValue as V
} }
return oldValue
} }
fun remove(key: String): V { override fun remove(key: K): V? {
val value = backingMap.get(key) if (key !is String) return null
if (!JsUtils.isUndefined(value)) { val value = backingMap[key]
backingMap.delete(key) if (value !== undefined) {
deleteProperty(backingMap, key!!)
size-- size--
structureChanged(host) // structureChanged(host)
return value as V
} }
else { 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 { override fun iterator(): MutableIterator<MutableEntry<K, V>> {
return !current.done 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> { override fun hasNext(): Boolean = iterator.hasNext()
last = current
current = entries.next() override fun next(): MutableEntry<K, V> {
return newMapEntry(last, valueMod) val key = iterator.next()
lastKey = key
return newMapEntry(key as K)
} }
override fun remove() { override fun remove() {
this@InternalStringMap.remove(last.getKey()) this@InternalStringMap.remove(checkNotNull(lastKey) as K)
} }
} }
} }
private fun newMapEntry(entry: InternalJsMap.IteratorEntry<V>, private fun newMapEntry(key: K): MutableEntry<K, V> = object : MutableEntry<K, V> {
lastValueMod: Int): Entry<K, V> { override val key: K get() = key
return object : AbstractMapEntry<K, V>() { override val value: V get() = this@InternalStringMap[key] as 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()
}
fun setValue(`object`: V): V { override fun setValue(value: V): V = this@InternalStringMap.put(key, value) as V
return put(entry.getKey(), `object`)
}
}
}
private fun <T> toNullIfUndefined(value: T): T? { override fun hashCode(): Int = AbstractMap.entryHashCode(this)
return if (JsUtils.isUndefined(value)) null else value 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 <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() override fun emptyMutableMapWithNullableKeyValue(): MutableMap<String?, Int?> = HashMap()
@test fun compareBehavior() { @test fun compareBehavior() {
+1 -1
View File
@@ -31,7 +31,7 @@ class ComplexSetJsTest : SetJsTest() {
} }
class PrimitiveSetJsTest : SetJsTest() { class PrimitiveSetJsTest : SetJsTest() {
override fun createEmptyMutableSet(): MutableSet<String> = HashSet() override fun createEmptyMutableSet(): MutableSet<String> = stringSetOf()
override fun createEmptyMutableSetWithNullableValues(): MutableSet<String?> = HashSet() override fun createEmptyMutableSetWithNullableValues(): MutableSet<String?> = HashSet()
@Test @Test
override fun constructors() { 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 JVM tests-->
<exclude name="**/*JVM.kt"/>
<exclude name="**/*JVMTest.kt"/> <exclude name="**/*JVMTest.kt"/>
<exclude name="**/*JVMTests.kt"/> <exclude name="**/*JVMTests.kt"/>