Refactor Map-InternalMap to provide specialized linked string map and set

This commit is contained in:
Ilya Gorbunov
2016-08-26 22:25:56 +03:00
parent e342593d2e
commit 23d2654afd
9 changed files with 67 additions and 32 deletions
@@ -100,26 +100,26 @@ open class HashMap<K, V> : AbstractMap<K, V> {
*/
private val internalMap: InternalMap<K, V>
internal val equality: EqualityComparator
private 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)
internal constructor(internalMap: InternalMap<K, V>) : super() {
this.internalMap = internalMap
this.equality = internalMap.equality
}
constructor() : this( { m -> InternalHashCodeMap(m) })
constructor() : this(InternalHashCodeMap(EqualityComparator.HashCode))
// init {
// reset()
// }
constructor(capacity: Int, loadFactor: Float = 0f) : this() {
constructor(initialCapacity: Int, loadFactor: Float = 0f) : this() {
// This implementation of HashMap has no need of load factors or capacities.
require(capacity >= 0) { "Negative initial capacity" }
require(initialCapacity >= 0) { "Negative initial capacity" }
require(loadFactor >= 0) { "Non-positive load factor" }
}
@@ -273,5 +273,5 @@ open class HashMap<K, V> : AbstractMap<K, V> {
public fun <V> stringMapOf(vararg pairs: Pair<String, V>): HashMap<String, V> {
return HashMap<String, V>({ m -> InternalStringMap(m) }).apply { putAll(pairs) }
return HashMap<String, V>(InternalStringMap(EqualityComparator.HashCode)).apply { putAll(pairs) }
}
@@ -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: HashMap<K, V>) : InternalMap<K, V> {
internal class InternalHashCodeMap<K, V>(override val equality: EqualityComparator) : InternalMap<K, V> {
private var backingMap: dynamic = js("Object.create(null)")
override var size: Int = 0
private set
override fun put(key: K, value: V): V? {
val hashCode = host.equality.getHashCode(key)
val hashCode = equality.getHashCode(key)
val chain = getChainOrNull(hashCode)
if (chain == null) {
// This is a new chain, put it to the map.
@@ -62,11 +62,11 @@ internal class InternalHashCodeMap<K, V>(private val host: HashMap<K, V>) : Inte
}
override fun remove(key: K): V? {
val hashCode = host.equality.getHashCode(key)
val hashCode = equality.getHashCode(key)
val chain = getChainOrNull(hashCode) ?: return null
for (index in 0..chain.size-1) {
val entry = chain[index]
if (host.equality.equals(key, entry.key)) {
if (equality.equals(key, entry.key)) {
if (chain.size == 1) {
chain.asDynamic().length = 0
// remove the whole array
@@ -94,10 +94,10 @@ internal class InternalHashCodeMap<K, V>(private val host: HashMap<K, V>) : Inte
override fun get(key: K): V? = getEntry(key)?.value
private fun getEntry(key: K): MutableEntry<K, V>? =
getChainOrNull(host.equality.getHashCode(key))?.findEntryInChain(key)
getChainOrNull(equality.getHashCode(key))?.findEntryInChain(key)
private fun Array<MutableEntry<K, V>>.findEntryInChain(key: K): MutableEntry<K, V>? =
firstOrNull { entry -> host.equality.equals(entry.key, key) }
firstOrNull { entry -> equality.equals(entry.key, key) }
override fun iterator(): MutableIterator<MutableEntry<K, V>> {
@@ -17,6 +17,7 @@
package kotlin.collections
internal interface InternalMap<K, V> : MutableIterable<MutableMap.MutableEntry<K, V>> {
val equality: EqualityComparator
val size: Int
operator fun contains(key: K): Boolean
operator fun get(key: K): V?
@@ -24,7 +24,7 @@ import kotlin.collections.MutableMap.MutableEntry
/**
* A simple wrapper around JavaScript Map for key type is string.
*/
internal class InternalStringMap<K, V>(private val host: HashMap<K, V>) : InternalMap<K, V> {
internal class InternalStringMap<K, V>(override val equality: EqualityComparator) : InternalMap<K, V> {
private var backingMap: dynamic = js("Object.create(null)")
override var size: Int = 0
@@ -162,35 +162,31 @@ open class LinkedHashMap<K, V> : HashMap<K, V>, Map<K, V> {
* duplicate the key here to eliminate changes to HashMap and minimize the
* code here, at the expense of additional space.
*/
private val map = HashMap<K, ChainEntry>()
private val map: HashMap<K, ChainEntry>
constructor() {
resetChainEntries()
constructor() : super() {
map = HashMap<K, ChainEntry>()
}
constructor(ignored: Int, alsoIgnored: Float = 0f) : super(ignored, alsoIgnored) {
resetChainEntries()
internal constructor(backingMap: HashMap<K, Any>) : super() {
map = backingMap as HashMap<K, ChainEntry>
}
// constructor(ignored: Int, alsoIgnored: Float, accessOrder: Boolean) : super(ignored, alsoIgnored) {
// this.accessOrder = accessOrder
// resetChainEntries()
// }
constructor(initialCapacity: Int, loadFactor: Float = 0f) : super(initialCapacity, loadFactor) {
map = HashMap<K, ChainEntry>()
}
constructor(original: Map<out K, V>) {
resetChainEntries()
map = HashMap<K, ChainEntry>()
this.putAll(original)
}
override fun clear() {
map.clear()
resetChainEntries()
}
private fun resetChainEntries() {
head = null
}
//
// override fun clone(): Any {
// return LinkedHashMap(this)
// }
@@ -265,3 +261,8 @@ open class LinkedHashMap<K, V> : HashMap<K, V>, Map<K, V> {
// }
}
}
public fun <V> linkedStringMapOf(vararg pairs: Pair<String, V>): LinkedHashMap<String, V> {
return LinkedHashMap<String, V>(stringMapOf<Any>()).apply { putAll(pairs) }
}
@@ -22,16 +22,22 @@ package kotlin.collections
open class LinkedHashSet<E> : HashSet<E> {
internal constructor(map: LinkedHashMap<E, Any>) : super(map)
constructor() : super(LinkedHashMap<E, Any>())
constructor(c: Collection<E>) : super(LinkedHashMap<E, Any>()) {
addAll(c)
}
constructor(capacity: Int, loadFactor: Float = 0.0f) : super(LinkedHashMap<E, Any>(capacity, loadFactor))
constructor(initialCapacity: Int, loadFactor: Float = 0.0f) : super(LinkedHashMap<E, Any>(initialCapacity, loadFactor))
// public override fun clone(): Any {
// return LinkedHashSet(this)
// }
}
public fun linkedStringSetOf(vararg elements: String): LinkedHashSet<String> {
return LinkedHashSet(linkedStringMapOf<Any>()).apply { addAll(elements) }
}