diff --git a/js/js.libraries/src/core/collections/AbstractMap.kt b/js/js.libraries/src/core/collections/AbstractMap.kt index 53bf3b681ba..fb73d13faf7 100644 --- a/js/js.libraries/src/core/collections/AbstractMap.kt +++ b/js/js.libraries/src/core/collections/AbstractMap.kt @@ -48,33 +48,37 @@ public abstract class AbstractMutableMap protected constructor() : Abstrac entries.clear() } + private var _keys: MutableSet? = null override val keys: MutableSet get() { - return object : AbstractMutableSet() { - override fun clear() { - this@AbstractMutableMap.clear() - } - - override operator fun contains(element: K): Boolean = containsKey(element) - - override operator fun iterator(): MutableIterator { - val outerIter = entries.iterator() - return object : MutableIterator { - override fun hasNext(): Boolean = outerIter.hasNext() - override fun next(): K = outerIter.next().key - override fun remove() = outerIter.remove() + if (_keys == null) { + _keys = object : AbstractMutableSet() { + override fun clear() { + this@AbstractMutableMap.clear() } - } - override fun remove(element: K): Boolean { - if (containsKey(element)) { - this@AbstractMutableMap.remove(element) - return true + override operator fun contains(element: K): Boolean = containsKey(element) + + override operator fun iterator(): MutableIterator { + val entryIterator = entries.iterator() + return object : MutableIterator { + override fun hasNext(): Boolean = entryIterator.hasNext() + override fun next(): K = entryIterator.next().key + override fun remove() = entryIterator.remove() + } } - return false - } - override val size: Int get() = this@AbstractMutableMap.size + override fun remove(element: K): Boolean { + if (containsKey(element)) { + this@AbstractMutableMap.remove(element) + return true + } + return false + } + + override val size: Int get() = this@AbstractMutableMap.size + } } + return _keys!! } override fun put(key: K, value: V): V? { @@ -87,31 +91,35 @@ public abstract class AbstractMutableMap protected constructor() : Abstrac } } + private var _values: MutableCollection? = null override val values: MutableCollection get() { - return object : AbstractMutableCollection() { - override fun clear() = this@AbstractMutableMap.clear() + if (_values == null) { + _values = object : AbstractMutableCollection() { + override fun clear() = this@AbstractMutableMap.clear() - override operator fun contains(element: V): Boolean = containsValue(element) + override operator fun contains(element: V): Boolean = containsValue(element) - override operator fun iterator(): MutableIterator { - val outerIter = entries.iterator() - return object : MutableIterator { - override fun hasNext(): Boolean = outerIter.hasNext() - override fun next(): V = outerIter.next().value - override fun remove() = outerIter.remove() + override operator fun iterator(): MutableIterator { + val entryIterator = entries.iterator() + return object : MutableIterator { + override fun hasNext(): Boolean = entryIterator.hasNext() + override fun next(): V = entryIterator.next().value + override fun remove() = entryIterator.remove() + } } - } - override val size: Int get() = this@AbstractMutableMap.size + override val size: Int get() = this@AbstractMutableMap.size - // TODO: should we implement them this way? Currently it's unspecified in JVM - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is Collection<*>) return false - return AbstractList.orderedEquals(this, other) + // TODO: should we implement them this way? Currently it's unspecified in JVM + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Collection<*>) return false + return AbstractList.orderedEquals(this, other) + } + override fun hashCode(): Int = AbstractList.orderedHashCode(this) } - override fun hashCode(): Int = AbstractList.orderedHashCode(this) } + return _values!! } override fun remove(key: K): V? { diff --git a/js/js.libraries/src/core/collections/HashMap.kt b/js/js.libraries/src/core/collections/HashMap.kt index 4f75a7baf26..bcfb5195d8a 100644 --- a/js/js.libraries/src/core/collections/HashMap.kt +++ b/js/js.libraries/src/core/collections/HashMap.kt @@ -80,8 +80,15 @@ public open class HashMap : AbstractMutableMap { override fun containsValue(value: V): Boolean = internalMap.any { equality.equals(it.value, value) } - override val entries: MutableSet> - get() = EntrySet() + private var _entries: MutableSet>? = null + override val entries: MutableSet> get() { + if (_entries == null) { + _entries = createEntrySet() + } + return _entries!! + } + + protected open fun createEntrySet(): MutableSet> = EntrySet() override operator fun get(key: K): V? = internalMap.get(key) diff --git a/js/js.libraries/src/core/collections/LinkedHashMap.kt b/js/js.libraries/src/core/collections/LinkedHashMap.kt index fc3a06a8ac8..b1ff86c4cf1 100644 --- a/js/js.libraries/src/core/collections/LinkedHashMap.kt +++ b/js/js.libraries/src/core/collections/LinkedHashMap.kt @@ -201,8 +201,7 @@ public open class LinkedHashMap : HashMap, Map { } - override val entries: MutableSet> - get() = EntrySet() + override fun createEntrySet(): MutableSet> = EntrySet() override operator fun get(key: K): V? = map.get(key)?.value diff --git a/libraries/stdlib/src/kotlin/collections/AbstractMap.kt b/libraries/stdlib/src/kotlin/collections/AbstractMap.kt index 2a78f02afa3..3dda4f2919f 100644 --- a/libraries/stdlib/src/kotlin/collections/AbstractMap.kt +++ b/libraries/stdlib/src/kotlin/collections/AbstractMap.kt @@ -62,21 +62,24 @@ public abstract class AbstractMap protected constructor() : Map override fun isEmpty(): Boolean = size == 0 override val size: Int get() = entries.size - + private @Volatile var _keys: Set? = null override val keys: Set get() { - return object : AbstractSet() { - override operator fun contains(element: K): Boolean = containsKey(element) + if (_keys == null) { + _keys = object : AbstractSet() { + override operator fun contains(element: K): Boolean = containsKey(element) - override operator fun iterator(): Iterator { - val outerIter = entries.iterator() - return object : Iterator { - override fun hasNext(): Boolean = outerIter.hasNext() - override fun next(): K = outerIter.next().key + override operator fun iterator(): Iterator { + val entryIterator = entries.iterator() + return object : Iterator { + override fun hasNext(): Boolean = entryIterator.hasNext() + override fun next(): K = entryIterator.next().key + } } - } - override val size: Int get() = this@AbstractMap.size + override val size: Int get() = this@AbstractMap.size + } } + return _keys!! } override fun toString(): String = entries.joinToString(", ", "{", "}") { toString(it) } @@ -85,28 +88,33 @@ public abstract class AbstractMap protected constructor() : Map private fun toString(o: Any?): String = if (o === this) "(this Map)" else o.toString() + private @Volatile var _values: Collection? = null override val values: Collection get() { - return object : AbstractCollection() { - override operator fun contains(element: @UnsafeVariance V): Boolean = containsValue(element) + if (_values == null) { + _values = object : AbstractCollection() { + override operator fun contains(element: @UnsafeVariance V): Boolean = containsValue(element) - override operator fun iterator(): Iterator { - val outerIter = entries.iterator() - return object : Iterator { - override fun hasNext(): Boolean = outerIter.hasNext() - override fun next(): V = outerIter.next().value + override operator fun iterator(): Iterator { + val entryIterator = entries.iterator() + return object : Iterator { + override fun hasNext(): Boolean = entryIterator.hasNext() + override fun next(): V = entryIterator.next().value + } } - } - override val size: Int get() = this@AbstractMap.size + override val size: Int get() = this@AbstractMap.size - // TODO: should we implement them this way? Currently it's unspecified in JVM - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is Collection<*>) return false - return AbstractList.orderedEquals(this, other) + // TODO: should we implement them this way? Currently it's unspecified in JVM + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Collection<*>) return false + return AbstractList.orderedEquals(this, other) + } + + override fun hashCode(): Int = AbstractList.orderedHashCode(this) } - override fun hashCode(): Int = AbstractList.orderedHashCode(this) } + return _values!! } private fun implFindEntry(key: K): Map.Entry? = entries.firstOrNull { it.key == key }