Maps and sets: cleanup, simplify, refactor.
#KT-12386
This commit is contained in:
@@ -20,42 +20,33 @@
|
|||||||
|
|
||||||
package kotlin.collections
|
package kotlin.collections
|
||||||
|
|
||||||
|
import kotlin.collections.Map.Entry
|
||||||
|
import kotlin.collections.MutableMap.MutableEntry
|
||||||
|
|
||||||
abstract class AbstractHashMap<K, V> : AbstractMap<K, V> {
|
abstract class AbstractHashMap<K, V> : AbstractMap<K, V> {
|
||||||
|
|
||||||
private inner class EntrySet : AbstractSet<Entry<K, V>>() {
|
private inner class EntrySet : AbstractSet<MutableEntry<K, V>>() {
|
||||||
|
|
||||||
override fun clear() {
|
override fun clear() {
|
||||||
this@AbstractHashMap.clear()
|
this@AbstractHashMap.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
override operator fun contains(o: Any?): Boolean {
|
override operator fun contains(element: MutableEntry<K, V>): Boolean = containsEntry(element)
|
||||||
if (o is Entry<*, *>) {
|
|
||||||
return containsEntry(o as Entry<*, *>?)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override operator fun iterator(): Iterator<Entry<K, V>> {
|
override operator fun iterator(): MutableIterator<MutableEntry<K, V>> = hashCodeMap.iterator()
|
||||||
return EntrySetIterator()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun remove(entry: Any?): Boolean {
|
override fun remove(entry: MutableEntry<K, V>): Boolean {
|
||||||
if (contains(entry)) {
|
if (contains(entry)) {
|
||||||
val key = (entry as Entry<*, *>).key
|
this@AbstractHashMap.remove(entry.key)
|
||||||
this@AbstractHashMap.remove(key)
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun size(): Int {
|
override val size: Int get() = this@AbstractHashMap.size
|
||||||
return this@AbstractHashMap.size
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Iterator for `EntrySet`.
|
|
||||||
*/
|
|
||||||
private inner class EntrySetIterator : Iterator<Entry<K, V>> {
|
private inner class EntrySetIterator : Iterator<Entry<K, V>> {
|
||||||
private val stringMapEntries = stringMap!!.iterator()
|
private val stringMapEntries = stringMap!!.iterator()
|
||||||
private var current: MutableIterator<Entry<K, V>> = stringMapEntries
|
private var current: MutableIterator<Entry<K, V>> = stringMapEntries
|
||||||
@@ -102,109 +93,103 @@ abstract class AbstractHashMap<K, V> : AbstractMap<K, V> {
|
|||||||
|
|
||||||
recordLastKnownStructure(this@AbstractHashMap, this)
|
recordLastKnownStructure(this@AbstractHashMap, this)
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A map of integral hashCodes onto entries.
|
* A map of integral hashCodes onto entries.
|
||||||
*/
|
*/
|
||||||
@Transient private var hashCodeMap: InternalHashCodeMap<K, V>? = null
|
private var hashCodeMap = InternalHashCodeMap<K, V>(this)
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* A map of Strings onto values.
|
// * A map of Strings onto values.
|
||||||
*/
|
// */
|
||||||
@Transient private var stringMap: InternalStringMap<K, V>? = null
|
// @Transient private var stringMap: InternalStringMap<K, V>? = null
|
||||||
|
|
||||||
constructor() {
|
constructor() : super()
|
||||||
reset()
|
// init {
|
||||||
}
|
// reset()
|
||||||
|
// }
|
||||||
|
|
||||||
@JvmOverloads constructor(ignored: Int, alsoIgnored: Float = 0f) {
|
constructor(capacity: Int, loadFactor: Float = 0f) : this() {
|
||||||
// This implementation of HashMap has no need of load factors or capacities.
|
// This implementation of HashMap has no need of load factors or capacities.
|
||||||
checkArgument(ignored >= 0, "Negative initial capacity")
|
require(capacity >= 0) { "Negative initial capacity" }
|
||||||
checkArgument(alsoIgnored >= 0, "Non-positive load factor")
|
require(loadFactor >= 0) { "Non-positive load factor" }
|
||||||
|
|
||||||
reset()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(toBeCopied: Map<out K, V>) {
|
constructor(original: Map<out K, V>) : this() {
|
||||||
reset()
|
this.putAll(original)
|
||||||
this.putAll(toBeCopied)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clear() {
|
override fun clear() {
|
||||||
reset()
|
// reset()
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private fun reset() {
|
// private fun reset() {
|
||||||
hashCodeMap = InternalHashCodeMap<K, V>(this)
|
hashCodeMap = InternalHashCodeMap<K, V>(this)
|
||||||
stringMap = InternalStringMap<K, V>(this)
|
// stringMap = InternalStringMap<K, V>(this)
|
||||||
structureChanged(this)
|
// structureChanged(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SpecializeMethod(params = { String.class }, target = "hasStringValue")
|
// @SpecializeMethod(params = { String.class }, target = "hasStringValue")
|
||||||
override fun containsKey(key: Any?): Boolean {
|
override fun containsKey(key: K): Boolean {
|
||||||
return if (key is String)
|
return hasHashValue(key)
|
||||||
hasStringValue(JsUtils.unsafeCastToString(key))
|
// return if (key is String)
|
||||||
else
|
// hasStringValue(JsUtils.unsafeCastToString(key))
|
||||||
hasHashValue(key)
|
// else
|
||||||
|
// hasHashValue(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun containsValue(value: Any?): Boolean {
|
override fun containsValue(value: V): Boolean {
|
||||||
return containsValue(value, stringMap) || containsValue(value, hashCodeMap)
|
return /*containsValue(value, stringMap) || */ containsValue(value, hashCodeMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun containsValue(value: Any, entries: Iterable<Entry<K, V>>): Boolean {
|
private fun containsValue(value: V, entries: Iterable<Entry<K, V>>): Boolean = entries.any { equals(it.value, value) }
|
||||||
for (entry in entries) {
|
|
||||||
if (equals(value, entry.value)) {
|
override val entries: MutableSet<MutableMap.MutableEntry<K, V>>
|
||||||
return true
|
get() = EntrySet()
|
||||||
}
|
|
||||||
}
|
// @SpecializeMethod(params = { String.class }, target = "getStringValue")
|
||||||
return false
|
override operator fun get(key: K): V? {
|
||||||
|
return getHashValue(key)
|
||||||
|
// return if (key is String)
|
||||||
|
// getStringValue(JsUtils.unsafeCastToString(key))
|
||||||
|
// else
|
||||||
|
// getHashValue(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun entrySet(): Set<Entry<K, V>> {
|
// @SpecializeMethod(params = { String.class, Object .class }, target = "putStringValue")
|
||||||
return EntrySet()
|
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 = "getStringValue")
|
// @SpecializeMethod(params = { String.class }, target = "removeStringValue")
|
||||||
override operator fun get(key: Any?): V {
|
override fun remove(key: K): V? {
|
||||||
return if (key is String)
|
return removeHashValue(key)
|
||||||
getStringValue(JsUtils.unsafeCastToString(key))
|
// return if (key is String)
|
||||||
else
|
// removeStringValue(JsUtils.unsafeCastToString(key))
|
||||||
getHashValue(key)
|
// else
|
||||||
|
// removeHashValue(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SpecializeMethod(params = { String.class, Object .class }, target = "putStringValue")
|
override val size: Int get() {
|
||||||
override fun put(key: K?, value: V?): V {
|
return hashCodeMap.size /*+ stringMap!!.size()*/
|
||||||
return if (key is String)
|
|
||||||
putStringValue(JsUtils.unsafeCastToString(key), value)
|
|
||||||
else
|
|
||||||
putHashValue(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
@SpecializeMethod(params = { String.class }, target = "removeStringValue")
|
|
||||||
override fun remove(key: Any?): V {
|
|
||||||
return if (key is String)
|
|
||||||
removeStringValue(JsUtils.unsafeCastToString(key))
|
|
||||||
else
|
|
||||||
removeHashValue(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun size(): Int {
|
|
||||||
return hashCodeMap!!.size() + stringMap!!.size()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclasses must override to return a whether or not two keys or values are
|
* Subclasses must override to return a whether or not two keys or values are
|
||||||
* equal.
|
* equal.
|
||||||
*/
|
*/
|
||||||
internal abstract fun equals(value1: Any, value2: Any): Boolean
|
internal abstract fun equals(value1: Any?, value2: Any?): Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclasses must override to return a hash code for a given key. The key is
|
* Subclasses must override to return a hash code for a given key. The key is
|
||||||
* guaranteed to be non-null and not a String.
|
* guaranteed to be non-null and not a String.
|
||||||
*/
|
*/
|
||||||
internal abstract fun getHashCode(key: Any): Int
|
internal abstract fun getHashCode(key: K): Int
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Map.Entry whose key is Object equal to `key`,
|
* Returns the Map.Entry whose key is Object equal to `key`,
|
||||||
@@ -212,51 +197,51 @@ abstract class AbstractHashMap<K, V> : AbstractMap<K, V> {
|
|||||||
* or `null` if no such Map.Entry exists at the specified
|
* or `null` if no such Map.Entry exists at the specified
|
||||||
* hashCode.
|
* hashCode.
|
||||||
*/
|
*/
|
||||||
private fun getHashValue(key: Any?): V {
|
private fun getHashValue(key: K): V? {
|
||||||
return getEntryValueOrNull(hashCodeMap!!.getEntry(key))
|
return hashCodeMap.getEntry(key)?.value
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Returns the value for the given key in the stringMap. Returns
|
// * Returns the value for the given key in the stringMap. Returns
|
||||||
* `null` if the specified key does not exist.
|
// * `null` if the specified key does not exist.
|
||||||
*/
|
// */
|
||||||
private fun getStringValue(key: String?): V {
|
// private fun getStringValue(key: String?): V {
|
||||||
return if (key == null) getHashValue(null) else stringMap!!.get(key)
|
// 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
|
* Returns true if the a key exists in the hashCodeMap that is Object equal to
|
||||||
* `key`, provided that `key`'s hash code is
|
* `key`, provided that `key`'s hash code is
|
||||||
* `hashCode`.
|
* `hashCode`.
|
||||||
*/
|
*/
|
||||||
private fun hasHashValue(key: Any?): Boolean {
|
private fun hasHashValue(key: K): Boolean {
|
||||||
return hashCodeMap!!.getEntry(key) != null
|
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)
|
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 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
|
* Sets the specified key to the specified value in the hashCodeMap. Returns
|
||||||
* the value previously at that key. Returns `null` if the
|
* the value previously at that key. Returns `null` if the
|
||||||
* specified key did not exist.
|
* specified key did not exist.
|
||||||
*/
|
*/
|
||||||
private fun putHashValue(key: K?, value: V): V {
|
private fun putHashValue(key: K, value: V): V? {
|
||||||
return hashCodeMap!!.put(key, value)
|
return hashCodeMap.put(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Sets the specified key to the specified value in the stringMap. Returns the
|
// * Sets the specified key to the specified value in the stringMap. Returns the
|
||||||
* value previously at that key. Returns `null` if the specified
|
// * value previously at that key. Returns `null` if the specified
|
||||||
* key did not exist.
|
// * key did not exist.
|
||||||
*/
|
// */
|
||||||
private fun putStringValue(key: String?, value: V): V {
|
// private fun putStringValue(key: String?, value: V): V {
|
||||||
return if (key == null) putHashValue(null, value) else stringMap!!.put(key, value)
|
// return if (key == null) putHashValue(null, value) else stringMap!!.put(key, value)
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the pair whose key is Object equal to `key` from
|
* Removes the pair whose key is Object equal to `key` from
|
||||||
@@ -264,16 +249,16 @@ abstract class AbstractHashMap<K, V> : AbstractMap<K, V> {
|
|||||||
* is `hashCode`. Returns the value that was associated with the
|
* is `hashCode`. Returns the value that was associated with the
|
||||||
* removed key, or null if no such key existed.
|
* removed key, or null if no such key existed.
|
||||||
*/
|
*/
|
||||||
private fun removeHashValue(key: Any?): V {
|
private fun removeHashValue(key: K): V? {
|
||||||
return hashCodeMap!!.remove(key)
|
return hashCodeMap.remove(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Removes the specified key from the stringMap and returns the value that was
|
// * Removes the specified key from the stringMap and returns the value that was
|
||||||
* previously there. Returns `null` if the specified key does not
|
// * previously there. Returns `null` if the specified key does not
|
||||||
* exist.
|
// * exist.
|
||||||
*/
|
// */
|
||||||
private fun removeStringValue(key: String?): V {
|
// private fun removeStringValue(key: String?): V {
|
||||||
return if (key == null) removeHashValue(null) else stringMap!!.remove(key)
|
// return if (key == null) removeHashValue(null) else stringMap!!.remove(key)
|
||||||
}
|
// }
|
||||||
}// This implementation of HashMap has no need of initial capacities.
|
}
|
||||||
@@ -66,7 +66,9 @@ abstract class AbstractMap<K, V> protected constructor() : MutableMap<K, V> {
|
|||||||
|
|
||||||
override fun containsValue(value: V): Boolean = entries.any { it.value == value }
|
override fun containsValue(value: V): Boolean = entries.any { it.value == value }
|
||||||
|
|
||||||
internal fun containsEntry(entry: Map.Entry<*, *>): Boolean {
|
internal fun containsEntry(entry: Map.Entry<*, *>?): Boolean {
|
||||||
|
// since entry comes from @UnsafeVariance parameters it can be virtually anything
|
||||||
|
if (entry !is Map.Entry<*, *>) return false
|
||||||
val key = entry.key
|
val key = entry.key
|
||||||
val value = entry.value
|
val value = entry.value
|
||||||
val ourValue = get(key)
|
val ourValue = get(key)
|
||||||
|
|||||||
@@ -20,45 +20,18 @@
|
|||||||
|
|
||||||
package kotlin.collections
|
package kotlin.collections
|
||||||
|
|
||||||
open class HashMap<K, V> : AbstractHashMap<K, V>, Cloneable, Serializable {
|
|
||||||
|
|
||||||
/**
|
open class HashMap<K, V> : AbstractHashMap<K, V> {
|
||||||
* Ensures that RPC will consider type parameter K to be exposed. It will be
|
|
||||||
* pruned by dead code elimination.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private val exposeKey: K? = null
|
|
||||||
|
|
||||||
/**
|
constructor() : super()
|
||||||
* Ensures that RPC will consider type parameter V to be exposed. It will be
|
constructor(capacity: Int, loadFactor: Float = 0f) : super(capacity, loadFactor)
|
||||||
* pruned by dead code elimination.
|
constructor(original: Map<out K, V>) : super(original)
|
||||||
*/
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private val exposeValue: V? = null
|
|
||||||
|
|
||||||
constructor() {
|
// public override fun clone(): Any {
|
||||||
}
|
// return HashMap<K, V>(this)
|
||||||
|
// }
|
||||||
|
|
||||||
constructor(ignored: Int) : super(ignored) {
|
override fun equals(value1: Any?, value2: Any?): Boolean = value1 == value2
|
||||||
}
|
|
||||||
|
|
||||||
constructor(ignored: Int, alsoIgnored: Float) : super(ignored, alsoIgnored) {
|
override fun getHashCode(key: K): Int = key?.hashCode() ?: 0
|
||||||
}
|
|
||||||
|
|
||||||
constructor(toBeCopied: Map<out K, V>) : super(toBeCopied) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun clone(): Any {
|
|
||||||
return HashMap<K, V>(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun equals(value1: Any, value2: Any): Boolean {
|
|
||||||
return value1 == value2
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun getHashCode(key: Any): Int {
|
|
||||||
val hashCode = key.hashCode()
|
|
||||||
// Coerce to int -- our classes all do this, but a user-written class might not.
|
|
||||||
return ensureInt(hashCode)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,22 +21,9 @@
|
|||||||
package kotlin.collections
|
package kotlin.collections
|
||||||
|
|
||||||
|
|
||||||
/**
|
open class HashSet<E> : AbstractSet<E> {
|
||||||
* Implements a set in terms of a hash table. [[Sun
|
|
||||||
* docs]](http://java.sun.com/j2se/1.5.0/docs/api/java/util/HashSet.html)
|
|
||||||
|
|
||||||
* @param element type.
|
private val map: HashMap<E, Any>
|
||||||
*/
|
|
||||||
open class HashSet<E> : AbstractSet<E>, Set<E>, Cloneable, Serializable {
|
|
||||||
|
|
||||||
@Transient private var map: HashMap<E, Any>? = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensures that RPC will consider type parameter E to be exposed. It will be
|
|
||||||
* pruned by dead code elimination.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private val exposeElement: E? = null
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
map = HashMap<E, Any>()
|
map = HashMap<E, Any>()
|
||||||
@@ -47,11 +34,7 @@ open class HashSet<E> : AbstractSet<E>, Set<E>, Cloneable, Serializable {
|
|||||||
addAll(c)
|
addAll(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(initialCapacity: Int) {
|
constructor(initialCapacity: Int, loadFactor: Float = 0.0f) {
|
||||||
map = HashMap<E, Any>(initialCapacity)
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(initialCapacity: Int, loadFactor: Float) {
|
|
||||||
map = HashMap<E, Any>(initialCapacity, loadFactor)
|
map = HashMap<E, Any>(initialCapacity, loadFactor)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,37 +48,27 @@ open class HashSet<E> : AbstractSet<E>, Set<E>, Cloneable, Serializable {
|
|||||||
this.map = map
|
this.map = map
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun add(o: E?): Boolean {
|
override fun add(element: E): Boolean {
|
||||||
val old = map!!.put(o, this)
|
val old = map.put(element, this)
|
||||||
return old == null
|
return old == null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clear() {
|
override fun clear() {
|
||||||
map!!.clear()
|
map.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun clone(): Any {
|
// public override fun clone(): Any {
|
||||||
return HashSet<E>(this)
|
// return HashSet<E>(this)
|
||||||
}
|
// }
|
||||||
|
|
||||||
override operator fun contains(o: Any?): Boolean {
|
override operator fun contains(element: E): Boolean = map.containsKey(element)
|
||||||
return map!!.containsKey(o)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isEmpty(): Boolean {
|
override fun isEmpty(): Boolean = map.isEmpty()
|
||||||
return map!!.isEmpty()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun iterator(): Iterator<E> {
|
override fun iterator(): MutableIterator<E> = map.keys.iterator()
|
||||||
return map!!.keys.iterator()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun remove(o: Any?): Boolean {
|
override fun remove(element: E): Boolean = map.remove(element) != null
|
||||||
return map!!.remove(o) != null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun size(): Int {
|
override val size: Int get() = map.size
|
||||||
return map!!.size
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,8 @@
|
|||||||
|
|
||||||
package kotlin.collections
|
package kotlin.collections
|
||||||
|
|
||||||
import java.util.ConcurrentModificationDetector.structureChanged
|
import kotlin.collections.MutableMap.MutableEntry
|
||||||
|
import kotlin.collections.AbstractMap.SimpleEntry
|
||||||
import java.util.AbstractMap.SimpleEntry
|
|
||||||
|
|
||||||
import javaemul.internal.ArrayHelper
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple wrapper around JavaScriptObject to provide [java.util.Map]-like semantics for any
|
* A simple wrapper around JavaScriptObject to provide [java.util.Map]-like semantics for any
|
||||||
@@ -38,126 +35,117 @@ import javaemul.internal.ArrayHelper
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
private class InternalHashCodeMap<K, V>(private val host: AbstractHashMap<K, V>) : Iterable<Entry<K, V>> {
|
internal class InternalHashCodeMap<K, V>(private val host: AbstractHashMap<K, V>) : MutableIterable<MutableEntry<K, V>> {
|
||||||
|
|
||||||
private val backingMap = InternalJsMapFactory.newJsMap()
|
private val backingMap: dynamic = js("new Object()")
|
||||||
private var size: Int = 0
|
var size: Int = 0
|
||||||
|
private set
|
||||||
|
|
||||||
fun put(key: K, value: V): V? {
|
fun put(key: K, value: V): V? {
|
||||||
val hashCode = hash(key)
|
val hashCode = host.getHashCode(key)
|
||||||
val chain = getChainOrEmpty(hashCode)
|
val chain = getChainOrNull(hashCode)
|
||||||
|
if (chain == null) {
|
||||||
if (chain.size == 0) {
|
|
||||||
// This is a new chain, put it to the map.
|
// This is a new chain, put it to the map.
|
||||||
backingMap.set(hashCode, chain)
|
backingMap[hashCode] = arrayOf(SimpleEntry(key, value))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Chain already exists, perhaps key also exists.
|
// Chain already exists, perhaps key also exists.
|
||||||
val entry = findEntryInChain(key, chain)
|
val entry = chain.findEntryInChain(key)
|
||||||
if (entry != null) {
|
if (entry != null) {
|
||||||
return entry!!.setValue(value)
|
return entry.setValue(value)
|
||||||
}
|
}
|
||||||
|
chain.asDynamic().push(SimpleEntry(key, value))
|
||||||
}
|
}
|
||||||
chain[chain.size] = SimpleEntry<K, V>(key, value)
|
|
||||||
size++
|
size++
|
||||||
structureChanged(host)
|
// structureChanged(host)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun remove(key: Any): V? {
|
fun remove(key: K): V? {
|
||||||
val hashCode = hash(key)
|
val hashCode = host.getHashCode(key)
|
||||||
val chain = getChainOrEmpty(hashCode)
|
val chain = getChainOrNull(hashCode) ?: return null
|
||||||
for (i in chain.indices) {
|
for (index in 0..chain.size-1) {
|
||||||
val entry = chain[i]
|
val entry = chain[index]
|
||||||
if (host.equals(key, entry.key)) {
|
if (host.equals(key, entry.key)) {
|
||||||
if (chain.size == 1) {
|
if (chain.size == 1) {
|
||||||
ArrayHelper.setLength(chain, 0)
|
chain.asDynamic().length = 0
|
||||||
// remove the whole array
|
// remove the whole array
|
||||||
backingMap.delete(hashCode)
|
deleteProperty(backingMap, hashCode)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// splice out the entry we're removing
|
// splice out the entry we're removing
|
||||||
ArrayHelper.removeFrom(chain, i, 1)
|
chain.asDynamic().splice(index, 1)
|
||||||
}
|
}
|
||||||
size--
|
size--
|
||||||
structureChanged(host)
|
// structureChanged(host)
|
||||||
return entry.value
|
return entry.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getEntry(key: Any): Entry<K, V> {
|
fun getEntry(key: K): MutableEntry<K, V>? =
|
||||||
return findEntryInChain(key, getChainOrEmpty(hash(key)))
|
getChainOrNull(host.getHashCode(key))?.findEntryInChain(key)
|
||||||
}
|
|
||||||
|
|
||||||
private fun findEntryInChain(key: Any, chain: Array<Entry<K, V>>): Entry<K, V>? {
|
private fun Array<MutableEntry<K, V>>.findEntryInChain(key: K): MutableEntry<K, V>? =
|
||||||
for (entry in chain) {
|
firstOrNull { entry -> host.equals(entry.key, key) }
|
||||||
if (host.equals(key, entry.key)) {
|
|
||||||
return entry
|
override fun iterator(): MutableIterator<MutableEntry<K, V>> {
|
||||||
|
|
||||||
|
return object : MutableIterator<MutableEntry<K, V>> {
|
||||||
|
var state = -1 // -1 not ready, 0 - ready, 1 - done
|
||||||
|
|
||||||
|
val keys: Array<Int> = js("Object").keys(backingMap)
|
||||||
|
var keyIndex = -1
|
||||||
|
|
||||||
|
var chain: Array<MutableEntry<K, V>>? = null
|
||||||
|
var itemIndex = -1
|
||||||
|
var lastEntry: MutableEntry<K, V>? = null
|
||||||
|
|
||||||
|
private fun computeNext(): Int {
|
||||||
|
if (chain != null) {
|
||||||
|
if (++itemIndex < chain!!.size)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++keyIndex < keys.size) {
|
||||||
|
chain = backingMap[keys[keyIndex]]
|
||||||
|
itemIndex = 0
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
chain = null
|
||||||
|
return 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun size(): Int {
|
|
||||||
return size
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun iterator(): Iterator<Entry<K, V>> {
|
|
||||||
return object : Iterator<Entry<K, V>> {
|
|
||||||
internal val chains = backingMap.entries()
|
|
||||||
internal var itemIndex = 0
|
|
||||||
internal var chain = newEntryChain()
|
|
||||||
internal var lastEntry: Entry<K, V>? = null
|
|
||||||
|
|
||||||
override fun hasNext(): Boolean {
|
override fun hasNext(): Boolean {
|
||||||
if (itemIndex < chain.size) {
|
if (state == -1)
|
||||||
return true
|
state = computeNext()
|
||||||
}
|
return state == 0
|
||||||
val current = chains.next()
|
|
||||||
if (!current.done) {
|
|
||||||
// Move to the beginning of next chain
|
|
||||||
chain = unsafeCastToArray(current.getValue())
|
|
||||||
itemIndex = 0
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun next(): Entry<K, V> {
|
override fun next(): MutableEntry<K, V> {
|
||||||
lastEntry = chain[itemIndex++]
|
if (!hasNext()) throw NoSuchElementException()
|
||||||
|
val lastEntry = chain!![itemIndex]
|
||||||
|
this.lastEntry = lastEntry
|
||||||
|
state = -1
|
||||||
return lastEntry
|
return lastEntry
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun remove() {
|
override fun remove() {
|
||||||
|
checkNotNull(lastEntry)
|
||||||
this@InternalHashCodeMap.remove(lastEntry!!.key)
|
this@InternalHashCodeMap.remove(lastEntry!!.key)
|
||||||
// Unless we are in a new chain, all items have shifted so our itemIndex should as well...
|
lastEntry = null
|
||||||
if (itemIndex != 0) {
|
// the chain being iterated just got modified by InternalHashCodeMap.remove
|
||||||
itemIndex--
|
itemIndex--
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getChainOrEmpty(hashCode: Int): Array<Entry<K, V>> {
|
private fun getChainOrNull(hashCode: Int): Array<MutableEntry<K, V>>? {
|
||||||
val chain = unsafeCastToArray(backingMap.get(hashCode))
|
val chain = backingMap[hashCode]
|
||||||
return chain ?: newEntryChain()
|
return if (chain !== undefined) chain else null // satisfying { it != undefined }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun newEntryChain(/*-{
|
|
||||||
return [];
|
|
||||||
}-*/): Array<Entry<K, V>>
|
|
||||||
|
|
||||||
private fun unsafeCastToArray(arr: Any /*-{
|
|
||||||
return arr;
|
|
||||||
}-*/): Array<Entry<K, V>>?
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns hash code of the key as calculated by [AbstractHashMap.getHashCode] but
|
|
||||||
* also handles null keys as well.
|
|
||||||
*/
|
|
||||||
private fun hash(key: Any?): Int {
|
|
||||||
return if (key == null) 0 else host.getHashCode(key)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
*/
|
*/
|
||||||
package kotlin.collections
|
package kotlin.collections
|
||||||
|
|
||||||
|
import kotlin.collections.MutableMap.MutableEntry
|
||||||
|
|
||||||
open class LinkedHashMap<K, V> : HashMap<K, V>, Map<K, V> {
|
open class LinkedHashMap<K, V> : HashMap<K, V>, Map<K, V> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,41 +35,59 @@ open class LinkedHashMap<K, V> : HashMap<K, V>, Map<K, V> {
|
|||||||
* small modifications. Paying a small storage cost only if you use
|
* small modifications. Paying a small storage cost only if you use
|
||||||
* LinkedHashMap and minimizing code size seemed like a better tradeoff
|
* LinkedHashMap and minimizing code size seemed like a better tradeoff
|
||||||
*/
|
*/
|
||||||
private inner class ChainEntry @JvmOverloads constructor(key: K? = null, value: V? = null) : AbstractMap.SimpleEntry<K, V>(key, value) {
|
private inner class ChainEntry(key: K, value: V) : AbstractMap.SimpleEntry<K, V>(key, value) {
|
||||||
@Transient private var next: ChainEntry? = null
|
internal var next: ChainEntry? = null
|
||||||
@Transient private var prev: ChainEntry? = null
|
internal var prev: ChainEntry? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add this node to the end of the chain.
|
* Add this node to the end of the chain.
|
||||||
*/
|
*/
|
||||||
fun addToEnd() {
|
fun addToEnd() {
|
||||||
val tail = head.prev
|
|
||||||
|
|
||||||
// Chain is valid.
|
|
||||||
assert(head != null && tail != null)
|
|
||||||
|
|
||||||
// This entry is not in the list.
|
// This entry is not in the list.
|
||||||
assert(next == null && prev == null)
|
check(next == null && prev == null)
|
||||||
|
|
||||||
|
if (head == null) {
|
||||||
|
head = this
|
||||||
|
next = this
|
||||||
|
prev = this
|
||||||
|
} else {
|
||||||
|
// Chain is valid.
|
||||||
|
val tail = checkNotNull(head).prev
|
||||||
|
checkNotNull(tail)
|
||||||
|
// Update me.
|
||||||
|
prev = tail
|
||||||
|
next = head
|
||||||
|
// Update my new siblings: current head and old tail
|
||||||
|
head!!.prev = this
|
||||||
|
tail!!.next = this
|
||||||
|
}
|
||||||
|
|
||||||
// Update me.
|
|
||||||
prev = tail
|
|
||||||
next = head
|
|
||||||
tail!!.next = head.prev = this
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove this node from any list it may be a part of.
|
* Remove this node from any list it may be a part of.
|
||||||
*/
|
*/
|
||||||
fun remove() {
|
fun remove() {
|
||||||
next!!.prev = prev
|
if (this.next === this) {
|
||||||
prev!!.next = next
|
// if this is single element, remove head
|
||||||
next = prev = null
|
head = null
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (head === this) {
|
||||||
|
// if this is first element, move head to next
|
||||||
|
head = next
|
||||||
|
}
|
||||||
|
next!!.prev = prev
|
||||||
|
prev!!.next = next
|
||||||
|
}
|
||||||
|
next = null
|
||||||
|
prev = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class EntrySet : AbstractSet<Entry<K, V>>() {
|
private inner class EntrySet : AbstractSet<MutableEntry<K, V>>() {
|
||||||
|
|
||||||
private inner class EntryIterator : Iterator<Entry<K, V>> {
|
private inner class EntryIterator : MutableIterator<MutableEntry<K, V>> {
|
||||||
// The last entry that was returned from this iterator.
|
// The last entry that was returned from this iterator.
|
||||||
private var last: ChainEntry? = null
|
private var last: ChainEntry? = null
|
||||||
|
|
||||||
@@ -75,30 +95,32 @@ open class LinkedHashMap<K, V> : HashMap<K, V>, Map<K, V> {
|
|||||||
private var next: ChainEntry? = null
|
private var next: ChainEntry? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
next = head.next
|
next = head
|
||||||
recordLastKnownStructure(map, this)
|
// recordLastKnownStructure(map, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hasNext(): Boolean {
|
override fun hasNext(): Boolean {
|
||||||
return next !== head
|
return next !== null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun next(): Entry<K, V> {
|
override fun next(): MutableEntry<K, V> {
|
||||||
checkStructuralChange(map, this)
|
// checkStructuralChange(map, this)
|
||||||
checkCriticalElement(hasNext())
|
if (!hasNext()) throw NoSuchElementException()
|
||||||
|
|
||||||
last = next
|
val current = next!!
|
||||||
next = next!!.next
|
last = current
|
||||||
return last
|
next = current.next
|
||||||
|
if (next === head) next = null // satisfying { it != head }
|
||||||
|
return current
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun remove() {
|
override fun remove() {
|
||||||
checkState(last != null)
|
check(last != null)
|
||||||
checkStructuralChange(map, this)
|
// checkStructuralChange(map, this)
|
||||||
|
|
||||||
last!!.remove()
|
last!!.remove()
|
||||||
map.remove(last!!.key)
|
map.remove(last!!.key)
|
||||||
recordLastKnownStructure(map, this)
|
// recordLastKnownStructure(map, this)
|
||||||
last = null
|
last = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,34 +129,24 @@ open class LinkedHashMap<K, V> : HashMap<K, V>, Map<K, V> {
|
|||||||
this@LinkedHashMap.clear()
|
this@LinkedHashMap.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
override operator fun contains(o: Any?): Boolean {
|
override operator fun contains(element: MutableEntry<K, V>): Boolean = containsEntry(element)
|
||||||
if (o is Entry<*, *>) {
|
|
||||||
return containsEntry(o as Entry<*, *>?)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override operator fun iterator(): Iterator<Entry<K, V>> {
|
override operator fun iterator(): MutableIterator<MutableEntry<K, V>> = EntryIterator()
|
||||||
return EntryIterator()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun remove(entry: Any?): Boolean {
|
override fun remove(entry: MutableEntry<K, V>): Boolean {
|
||||||
if (contains(entry)) {
|
if (contains(entry)) {
|
||||||
val key = (entry as Entry<*, *>).key
|
this@LinkedHashMap.remove(entry.key)
|
||||||
this@LinkedHashMap.remove(key)
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun size(): Int {
|
override val size: Int get() = this@LinkedHashMap.size
|
||||||
return this@LinkedHashMap.size
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// True if we should use the access order (ie, for LRU caches) instead of
|
// // True if we should use the access order (ie, for LRU caches) instead of
|
||||||
// insertion order.
|
// // insertion order.
|
||||||
@Transient private val accessOrder: Boolean
|
// private val accessOrder: Boolean
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The head of the LRU/insert order chain, which is a doubly-linked circular
|
* The head of the LRU/insert order chain, which is a doubly-linked circular
|
||||||
@@ -143,31 +155,31 @@ open class LinkedHashMap<K, V> : HashMap<K, V>, Map<K, V> {
|
|||||||
* The most recently inserted/accessed node is at the end of the chain, ie.
|
* The most recently inserted/accessed node is at the end of the chain, ie.
|
||||||
* chain.prev.
|
* chain.prev.
|
||||||
*/
|
*/
|
||||||
@Transient private val head = ChainEntry()
|
private var head: ChainEntry? = null
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The hashmap that keeps track of our entries and the chain. Note that we
|
* The hashmap that keeps track of our entries and the chain. Note that we
|
||||||
* duplicate the key here to eliminate changes to HashMap and minimize the
|
* duplicate the key here to eliminate changes to HashMap and minimize the
|
||||||
* code here, at the expense of additional space.
|
* code here, at the expense of additional space.
|
||||||
*/
|
*/
|
||||||
@Transient private val map = HashMap<K, ChainEntry>()
|
private val map = HashMap<K, ChainEntry>()
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
resetChainEntries()
|
resetChainEntries()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmOverloads constructor(ignored: Int, alsoIgnored: Float = 0f) : super(ignored, alsoIgnored) {
|
constructor(ignored: Int, alsoIgnored: Float = 0f) : super(ignored, alsoIgnored) {
|
||||||
resetChainEntries()
|
resetChainEntries()
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(ignored: Int, alsoIgnored: Float, accessOrder: Boolean) : super(ignored, alsoIgnored) {
|
// constructor(ignored: Int, alsoIgnored: Float, accessOrder: Boolean) : super(ignored, alsoIgnored) {
|
||||||
this.accessOrder = accessOrder
|
// this.accessOrder = accessOrder
|
||||||
resetChainEntries()
|
// resetChainEntries()
|
||||||
}
|
// }
|
||||||
|
|
||||||
constructor(toBeCopied: Map<out K, V>) {
|
constructor(original: Map<out K, V>) {
|
||||||
resetChainEntries()
|
resetChainEntries()
|
||||||
this.putAll(toBeCopied)
|
this.putAll(original)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clear() {
|
override fun clear() {
|
||||||
@@ -176,85 +188,80 @@ open class LinkedHashMap<K, V> : HashMap<K, V>, Map<K, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun resetChainEntries() {
|
private fun resetChainEntries() {
|
||||||
head.prev = head
|
head = null
|
||||||
head.next = head
|
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// override fun clone(): Any {
|
||||||
|
// return LinkedHashMap(this)
|
||||||
|
// }
|
||||||
|
|
||||||
override fun clone(): Any {
|
override fun containsKey(key: K): Boolean = map.containsKey(key)
|
||||||
return LinkedHashMap(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun containsKey(key: Any?): Boolean {
|
override fun containsValue(value: V): Boolean {
|
||||||
return map.containsKey(key)
|
var node: ChainEntry = head ?: return false
|
||||||
}
|
do {
|
||||||
|
|
||||||
override fun containsValue(value: Any?): Boolean {
|
|
||||||
var node: ChainEntry = head.next
|
|
||||||
while (node !== head) {
|
|
||||||
if (node.value == value) {
|
if (node.value == value) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
node = node.next
|
node = node.next!!
|
||||||
}
|
} while (node !== head)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun entrySet(): Set<Entry<K, V>> {
|
|
||||||
return EntrySet()
|
|
||||||
}
|
|
||||||
|
|
||||||
override operator fun get(key: Any?): V? {
|
override val entries: MutableSet<MutableMap.MutableEntry<K, V>>
|
||||||
|
get() = EntrySet()
|
||||||
|
|
||||||
|
override operator fun get(key: K): V? {
|
||||||
val entry = map.get(key)
|
val entry = map.get(key)
|
||||||
if (entry != null) {
|
if (entry != null) {
|
||||||
recordAccess(entry)
|
recordAccess(entry)
|
||||||
return entry!!.value
|
return entry.value
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun put(key: K?, value: V?): V? {
|
override fun put(key: K, value: V): V? {
|
||||||
val old = map.get(key)
|
val old = map.get(key)
|
||||||
if (old == null) {
|
if (old == null) {
|
||||||
val newEntry = ChainEntry(key, value)
|
val newEntry = ChainEntry(key, value)
|
||||||
map.put(key, newEntry)
|
map.put(key, newEntry)
|
||||||
newEntry.addToEnd()
|
newEntry.addToEnd()
|
||||||
val eldest = head.next
|
// val eldest = head.next!!
|
||||||
if (removeEldestEntry(eldest)) {
|
// if (removeEldestEntry(eldest)) {
|
||||||
eldest!!.remove()
|
// eldest.remove()
|
||||||
map.remove(eldest.key)
|
// map.remove(eldest.key)
|
||||||
}
|
// }
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val oldValue = old!!.setValue(value)
|
val oldValue = old.setValue(value)
|
||||||
recordAccess(old)
|
recordAccess(old)
|
||||||
return oldValue
|
return oldValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun remove(key: Any?): V? {
|
override fun remove(key: K): V? {
|
||||||
val entry = map.remove(key)
|
val entry = map.remove(key)
|
||||||
if (entry != null) {
|
if (entry != null) {
|
||||||
entry!!.remove()
|
entry.remove()
|
||||||
return entry!!.value
|
return entry.value
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun size(): Int {
|
override val size: Int get() = map.size
|
||||||
return map.size
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
// @SuppressWarnings("unused")
|
||||||
protected fun removeEldestEntry(eldest: Entry<K, V>): Boolean {
|
// protected fun removeEldestEntry(eldest: Entry<K, V>): Boolean {
|
||||||
return false
|
// return false
|
||||||
}
|
// }
|
||||||
|
|
||||||
private fun recordAccess(entry: ChainEntry) {
|
private fun recordAccess(entry: ChainEntry) {
|
||||||
if (accessOrder) {
|
// if (accessOrder) {
|
||||||
// Move to the tail of the chain on access.
|
// // Move to the tail of the chain on access.
|
||||||
entry.remove()
|
// entry.remove()
|
||||||
entry.addToEnd()
|
// entry.addToEnd()
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ open class LinkedHashSet<E> : HashSet<E> {
|
|||||||
addAll(c)
|
addAll(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(capacity: Int) : super(LinkedHashMap<E, Any>(capacity))
|
|
||||||
constructor(capacity: Int, loadFactor: Float = 0.0f) : super(LinkedHashMap<E, Any>(capacity, loadFactor))
|
constructor(capacity: Int, loadFactor: Float = 0.0f) : super(LinkedHashMap<E, Any>(capacity, loadFactor))
|
||||||
|
|
||||||
// public override fun clone(): Any {
|
// public override fun clone(): Any {
|
||||||
|
|||||||
@@ -40,3 +40,6 @@ public fun js(code: String): dynamic = noImpl
|
|||||||
* Function corresponding to JavaScript's `typeof` operator
|
* Function corresponding to JavaScript's `typeof` operator
|
||||||
*/
|
*/
|
||||||
public inline fun jsTypeOf(a: Any?): String = js("typeof a")
|
public inline fun jsTypeOf(a: Any?): String = js("typeof a")
|
||||||
|
|
||||||
|
@library
|
||||||
|
internal fun deleteProperty(`object`: Any, property: Any): Unit = noImpl
|
||||||
+4
@@ -902,6 +902,10 @@
|
|||||||
return new Kotlin.ArrayIterator(array);
|
return new Kotlin.ArrayIterator(array);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Kotlin.deleteProperty = function (object, property) {
|
||||||
|
delete object[property];
|
||||||
|
};
|
||||||
|
|
||||||
Kotlin.jsonAddProperties = function (obj1, obj2) {
|
Kotlin.jsonAddProperties = function (obj1, obj2) {
|
||||||
for (var p in obj2) {
|
for (var p in obj2) {
|
||||||
if (obj2.hasOwnProperty(p)) {
|
if (obj2.hasOwnProperty(p)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user