Refactor Map-InternalMap to provide specialized linked string map and set
This commit is contained in:
@@ -100,26 +100,26 @@ open class HashMap<K, V> : AbstractMap<K, V> {
|
|||||||
*/
|
*/
|
||||||
private val internalMap: InternalMap<K, V>
|
private val internalMap: InternalMap<K, V>
|
||||||
|
|
||||||
internal val equality: EqualityComparator
|
private val equality: EqualityComparator
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
// * 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
|
||||||
//
|
//
|
||||||
internal constructor(internalMapProvider: (HashMap<K, V>) -> InternalMap<K, V>, equality: EqualityComparator = EqualityComparator.HashCode) : super() {
|
internal constructor(internalMap: InternalMap<K, V>) : super() {
|
||||||
this.equality = equality
|
this.internalMap = internalMap
|
||||||
this.internalMap = internalMapProvider(this)
|
this.equality = internalMap.equality
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() : this( { m -> InternalHashCodeMap(m) })
|
constructor() : this(InternalHashCodeMap(EqualityComparator.HashCode))
|
||||||
// init {
|
// init {
|
||||||
// reset()
|
// 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.
|
// 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" }
|
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> {
|
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
|
* 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: 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)")
|
private var backingMap: dynamic = js("Object.create(null)")
|
||||||
override var size: Int = 0
|
override var size: Int = 0
|
||||||
private set
|
private set
|
||||||
|
|
||||||
override fun put(key: K, value: V): V? {
|
override fun put(key: K, value: V): V? {
|
||||||
val hashCode = host.equality.getHashCode(key)
|
val hashCode = 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.
|
||||||
@@ -62,11 +62,11 @@ internal class InternalHashCodeMap<K, V>(private val host: HashMap<K, V>) : Inte
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun remove(key: K): V? {
|
override fun remove(key: K): V? {
|
||||||
val hashCode = host.equality.getHashCode(key)
|
val hashCode = 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.equality.equals(key, entry.key)) {
|
if (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
|
||||||
@@ -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
|
override fun get(key: K): V? = getEntry(key)?.value
|
||||||
|
|
||||||
private fun getEntry(key: K): MutableEntry<K, V>? =
|
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>? =
|
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>> {
|
override fun iterator(): MutableIterator<MutableEntry<K, V>> {
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package kotlin.collections
|
package kotlin.collections
|
||||||
|
|
||||||
internal interface InternalMap<K, V> : MutableIterable<MutableMap.MutableEntry<K, V>> {
|
internal interface InternalMap<K, V> : MutableIterable<MutableMap.MutableEntry<K, V>> {
|
||||||
|
val equality: EqualityComparator
|
||||||
val size: Int
|
val size: Int
|
||||||
operator fun contains(key: K): Boolean
|
operator fun contains(key: K): Boolean
|
||||||
operator fun get(key: K): V?
|
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.
|
* 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)")
|
private var backingMap: dynamic = js("Object.create(null)")
|
||||||
override var size: Int = 0
|
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
|
* 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.
|
||||||
*/
|
*/
|
||||||
private val map = HashMap<K, ChainEntry>()
|
private val map: HashMap<K, ChainEntry>
|
||||||
|
|
||||||
constructor() {
|
constructor() : super() {
|
||||||
resetChainEntries()
|
map = HashMap<K, ChainEntry>()
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(ignored: Int, alsoIgnored: Float = 0f) : super(ignored, alsoIgnored) {
|
internal constructor(backingMap: HashMap<K, Any>) : super() {
|
||||||
resetChainEntries()
|
map = backingMap as HashMap<K, ChainEntry>
|
||||||
}
|
}
|
||||||
|
|
||||||
// constructor(ignored: Int, alsoIgnored: Float, accessOrder: Boolean) : super(ignored, alsoIgnored) {
|
constructor(initialCapacity: Int, loadFactor: Float = 0f) : super(initialCapacity, loadFactor) {
|
||||||
// this.accessOrder = accessOrder
|
map = HashMap<K, ChainEntry>()
|
||||||
// resetChainEntries()
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
constructor(original: Map<out K, V>) {
|
constructor(original: Map<out K, V>) {
|
||||||
resetChainEntries()
|
map = HashMap<K, ChainEntry>()
|
||||||
this.putAll(original)
|
this.putAll(original)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clear() {
|
override fun clear() {
|
||||||
map.clear()
|
map.clear()
|
||||||
resetChainEntries()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun resetChainEntries() {
|
|
||||||
head = null
|
head = null
|
||||||
}
|
}
|
||||||
//
|
|
||||||
|
|
||||||
// override fun clone(): Any {
|
// override fun clone(): Any {
|
||||||
// return LinkedHashMap(this)
|
// 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> {
|
open class LinkedHashSet<E> : HashSet<E> {
|
||||||
|
|
||||||
|
internal constructor(map: LinkedHashMap<E, Any>) : super(map)
|
||||||
|
|
||||||
constructor() : super(LinkedHashMap<E, Any>())
|
constructor() : super(LinkedHashMap<E, Any>())
|
||||||
|
|
||||||
constructor(c: Collection<E>) : super(LinkedHashMap<E, Any>()) {
|
constructor(c: Collection<E>) : super(LinkedHashMap<E, Any>()) {
|
||||||
addAll(c)
|
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 {
|
// public override fun clone(): Any {
|
||||||
// return LinkedHashSet(this)
|
// return LinkedHashSet(this)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun linkedStringSetOf(vararg elements: String): LinkedHashSet<String> {
|
||||||
|
return LinkedHashSet(linkedStringMapOf<Any>()).apply { addAll(elements) }
|
||||||
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class PrimitiveMapJsTest : MapJsTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LinkedHashMapTest : MapJsTest() {
|
class LinkedHashMapJsTest : MapJsTest() {
|
||||||
@test override fun constructors() {
|
@test override fun constructors() {
|
||||||
LinkedHashMap<String, Int>()
|
LinkedHashMap<String, Int>()
|
||||||
LinkedHashMap<String, Int>(3)
|
LinkedHashMap<String, Int>(3)
|
||||||
@@ -72,6 +72,19 @@ class LinkedHashMapTest : MapJsTest() {
|
|||||||
override fun emptyMutableMapWithNullableKeyValue(): MutableMap<String?, Int?> = LinkedHashMap()
|
override fun emptyMutableMapWithNullableKeyValue(): MutableMap<String?, Int?> = LinkedHashMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class LinkedPrimitiveMapJsTest : MapJsTest() {
|
||||||
|
@test override fun constructors() {
|
||||||
|
val map = createTestMap()
|
||||||
|
|
||||||
|
assertEquals(KEYS.toNormalizedList(), map.keys.toNormalizedList())
|
||||||
|
assertEquals(VALUES.toNormalizedList(), map.values.toNormalizedList())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : kotlin.Comparable<T>> Collection<T>.toNormalizedList(): List<T> = this.toList()
|
||||||
|
override fun emptyMutableMap(): MutableMap<String, Int> = linkedStringMapOf()
|
||||||
|
override fun emptyMutableMapWithNullableKeyValue(): MutableMap<String?, Int?> = LinkedHashMap()
|
||||||
|
}
|
||||||
|
|
||||||
abstract class MapJsTest {
|
abstract class MapJsTest {
|
||||||
val KEYS = listOf("zero", "one", "two", "three")
|
val KEYS = listOf("zero", "one", "two", "three")
|
||||||
val VALUES = arrayOf(0, 1, 2, 3).toList()
|
val VALUES = arrayOf(0, 1, 2, 3).toList()
|
||||||
|
|||||||
@@ -72,6 +72,18 @@ class LinkedHashSetJsTest : SetJsTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class LinkedPrimitiveSetJsTest : SetJsTest() {
|
||||||
|
override fun createEmptyMutableSet(): MutableSet<String> = linkedStringSetOf()
|
||||||
|
override fun createEmptyMutableSetWithNullableValues(): MutableSet<String?> = LinkedHashSet()
|
||||||
|
@Test
|
||||||
|
override fun constructors() {
|
||||||
|
val orderedData = data.toList()
|
||||||
|
val set = linkedStringSetOf(*orderedData.toTypedArray())
|
||||||
|
|
||||||
|
assertEquals(orderedData, set.toList())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
abstract class SetJsTest {
|
abstract class SetJsTest {
|
||||||
val data: Set<String> = createTestMutableSet()
|
val data: Set<String> = createTestMutableSet()
|
||||||
val empty: Set<String> = createEmptyMutableSet()
|
val empty: Set<String> = createEmptyMutableSet()
|
||||||
|
|||||||
@@ -19,4 +19,6 @@ package test.collections.js
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public fun <V> stringMapOf(vararg pairs: Pair<String, V>): HashMap<String, V> = hashMapOf<String, V>(*pairs)
|
public fun <V> stringMapOf(vararg pairs: Pair<String, V>): HashMap<String, V> = hashMapOf<String, V>(*pairs)
|
||||||
|
public fun <V> linkedStringMapOf(vararg pairs: Pair<String, V>): LinkedHashMap<String, V> = linkedMapOf(*pairs)
|
||||||
public fun stringSetOf(vararg elements: String): HashSet<String> = hashSetOf(*elements)
|
public fun stringSetOf(vararg elements: String): HashSet<String> = hashSetOf(*elements)
|
||||||
|
public fun linkedStringSetOf(vararg elements: String): LinkedHashSet<String> = linkedSetOf(*elements)
|
||||||
|
|||||||
Reference in New Issue
Block a user