Do not recreate entries, keys and values collections on each access to property.

This commit is contained in:
Ilya Gorbunov
2016-09-13 22:37:20 +03:00
parent c6654fc9d8
commit f88a009653
4 changed files with 89 additions and 67 deletions
@@ -48,33 +48,37 @@ public abstract class AbstractMutableMap<K, V> protected constructor() : Abstrac
entries.clear() entries.clear()
} }
private var _keys: MutableSet<K>? = null
override val keys: MutableSet<K> get() { override val keys: MutableSet<K> get() {
return object : AbstractMutableSet<K>() { if (_keys == null) {
override fun clear() { _keys = object : AbstractMutableSet<K>() {
this@AbstractMutableMap.clear() override fun clear() {
} this@AbstractMutableMap.clear()
override operator fun contains(element: K): Boolean = containsKey(element)
override operator fun iterator(): MutableIterator<K> {
val outerIter = entries.iterator()
return object : MutableIterator<K> {
override fun hasNext(): Boolean = outerIter.hasNext()
override fun next(): K = outerIter.next().key
override fun remove() = outerIter.remove()
} }
}
override fun remove(element: K): Boolean { override operator fun contains(element: K): Boolean = containsKey(element)
if (containsKey(element)) {
this@AbstractMutableMap.remove(element) override operator fun iterator(): MutableIterator<K> {
return true val entryIterator = entries.iterator()
return object : MutableIterator<K> {
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? { override fun put(key: K, value: V): V? {
@@ -87,31 +91,35 @@ public abstract class AbstractMutableMap<K, V> protected constructor() : Abstrac
} }
} }
private var _values: MutableCollection<V>? = null
override val values: MutableCollection<V> get() { override val values: MutableCollection<V> get() {
return object : AbstractMutableCollection<V>() { if (_values == null) {
override fun clear() = this@AbstractMutableMap.clear() _values = object : AbstractMutableCollection<V>() {
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<V> { override operator fun iterator(): MutableIterator<V> {
val outerIter = entries.iterator() val entryIterator = entries.iterator()
return object : MutableIterator<V> { return object : MutableIterator<V> {
override fun hasNext(): Boolean = outerIter.hasNext() override fun hasNext(): Boolean = entryIterator.hasNext()
override fun next(): V = outerIter.next().value override fun next(): V = entryIterator.next().value
override fun remove() = outerIter.remove() 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 // TODO: should we implement them this way? Currently it's unspecified in JVM
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other !is Collection<*>) return false if (other !is Collection<*>) return false
return AbstractList.orderedEquals(this, other) 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? { override fun remove(key: K): V? {
@@ -80,8 +80,15 @@ public open class HashMap<K, V> : AbstractMutableMap<K, V> {
override fun containsValue(value: V): Boolean = internalMap.any { equality.equals(it.value, value) } override fun containsValue(value: V): Boolean = internalMap.any { equality.equals(it.value, value) }
override val entries: MutableSet<MutableMap.MutableEntry<K, V>> private var _entries: MutableSet<MutableMap.MutableEntry<K, V>>? = null
get() = EntrySet() override val entries: MutableSet<MutableMap.MutableEntry<K, V>> get() {
if (_entries == null) {
_entries = createEntrySet()
}
return _entries!!
}
protected open fun createEntrySet(): MutableSet<MutableMap.MutableEntry<K, V>> = EntrySet()
override operator fun get(key: K): V? = internalMap.get(key) override operator fun get(key: K): V? = internalMap.get(key)
@@ -201,8 +201,7 @@ public open class LinkedHashMap<K, V> : HashMap<K, V>, Map<K, V> {
} }
override val entries: MutableSet<MutableMap.MutableEntry<K, V>> override fun createEntrySet(): MutableSet<MutableMap.MutableEntry<K, V>> = EntrySet()
get() = EntrySet()
override operator fun get(key: K): V? = map.get(key)?.value override operator fun get(key: K): V? = map.get(key)?.value
@@ -62,21 +62,24 @@ public abstract class AbstractMap<K, out V> protected constructor() : Map<K, V>
override fun isEmpty(): Boolean = size == 0 override fun isEmpty(): Boolean = size == 0
override val size: Int get() = entries.size override val size: Int get() = entries.size
private @Volatile var _keys: Set<K>? = null
override val keys: Set<K> get() { override val keys: Set<K> get() {
return object : AbstractSet<K>() { if (_keys == null) {
override operator fun contains(element: K): Boolean = containsKey(element) _keys = object : AbstractSet<K>() {
override operator fun contains(element: K): Boolean = containsKey(element)
override operator fun iterator(): Iterator<K> { override operator fun iterator(): Iterator<K> {
val outerIter = entries.iterator() val entryIterator = entries.iterator()
return object : Iterator<K> { return object : Iterator<K> {
override fun hasNext(): Boolean = outerIter.hasNext() override fun hasNext(): Boolean = entryIterator.hasNext()
override fun next(): K = outerIter.next().key 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) } override fun toString(): String = entries.joinToString(", ", "{", "}") { toString(it) }
@@ -85,28 +88,33 @@ public abstract class AbstractMap<K, out V> protected constructor() : Map<K, V>
private fun toString(o: Any?): String = if (o === this) "(this Map)" else o.toString() private fun toString(o: Any?): String = if (o === this) "(this Map)" else o.toString()
private @Volatile var _values: Collection<V>? = null
override val values: Collection<V> get() { override val values: Collection<V> get() {
return object : AbstractCollection<V>() { if (_values == null) {
override operator fun contains(element: @UnsafeVariance V): Boolean = containsValue(element) _values = object : AbstractCollection<V>() {
override operator fun contains(element: @UnsafeVariance V): Boolean = containsValue(element)
override operator fun iterator(): Iterator<V> { override operator fun iterator(): Iterator<V> {
val outerIter = entries.iterator() val entryIterator = entries.iterator()
return object : Iterator<V> { return object : Iterator<V> {
override fun hasNext(): Boolean = outerIter.hasNext() override fun hasNext(): Boolean = entryIterator.hasNext()
override fun next(): V = outerIter.next().value 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 // TODO: should we implement them this way? Currently it's unspecified in JVM
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other !is Collection<*>) return false if (other !is Collection<*>) return false
return AbstractList.orderedEquals(this, other) 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<K, V>? = entries.firstOrNull { it.key == key } private fun implFindEntry(key: K): Map.Entry<K, V>? = entries.firstOrNull { it.key == key }