Skip to content

Commit 82d71e5

Browse files
committed
Refactor PersistentOrderedMap and Set
1 parent 3794c25 commit 82d71e5

File tree

7 files changed

+148
-128
lines changed

7 files changed

+148
-128
lines changed

kotlinx-collections-immutable/src/main/kotlin/kotlinx/collections/immutable/implementations/persistentOrderedMap/PersistentOrderedMap.kt

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,27 +22,32 @@ import kotlinx.collections.immutable.PersistentMap
2222
import kotlinx.collections.immutable.implementations.immutableMap.PersistentHashMap
2323
import kotlinx.collections.immutable.mutate
2424

25-
internal object EndOfLink
25+
internal object EndOfChain
2626

2727
internal class LinkedValue<V>(val value: V, val previous: Any?, val next: Any?) {
28-
constructor(value: V) : this(value, EndOfLink, EndOfLink)
28+
constructor(value: V) : this(value, EndOfChain, EndOfChain)
2929

3030
fun withValue(newValue: V) = LinkedValue(newValue, previous, next)
3131
fun withPrevious(newPrevious: Any?) = LinkedValue(value, newPrevious, next)
3232
fun withNext(newNext: Any?) = LinkedValue(value, previous, newNext)
3333

34+
val hasNext get() = next !== EndOfChain
35+
val hasPrevious get() = previous !== EndOfChain
36+
37+
// TODO: it doesn't use 'this', can be made static
3438
fun putNextLink(value: V, previous: Any?): LinkedValue<V> {
35-
// assert(next === EndOfLink)
36-
return LinkedValue(value, previous, EndOfLink)
39+
// assert(next === EndOfChain)
40+
return LinkedValue(value, previous, EndOfChain)
3741
}
3842
}
3943

40-
internal class PersistentOrderedMap<K, V>(internal val firstKey: Any?,
41-
internal val lastKey: Any?,
42-
internal val map: PersistentHashMap<K, LinkedValue<V>>): AbstractMap<K, V>(), PersistentMap<K, V> {
44+
internal class PersistentOrderedMap<K, V>(
45+
internal val firstKey: Any?,
46+
internal val lastKey: Any?,
47+
internal val hashMap: PersistentHashMap<K, LinkedValue<V>>
48+
) : AbstractMap<K, V>(), PersistentMap<K, V> {
4349

44-
override val size: Int
45-
get() = map.size
50+
override val size: Int get() = hashMap.size
4651

4752
override val keys: ImmutableSet<K>
4853
get() {
@@ -69,59 +74,59 @@ internal class PersistentOrderedMap<K, V>(internal val firstKey: Any?,
6974
return createEntries()
7075
}
7176

72-
override fun containsKey(key: K): Boolean {
73-
return map.containsKey(key)
74-
}
77+
override fun containsKey(key: K): Boolean = hashMap.containsKey(key)
7578

76-
override fun get(key: K): V? {
77-
return map[key]?.value
78-
}
79+
override fun get(key: K): V? = hashMap[key]?.value
7980

8081
override fun put(key: K, value: @UnsafeVariance V): PersistentOrderedMap<K, V> {
8182
if (isEmpty()) {
82-
val newMap = map.put(key, LinkedValue(value))
83+
val newMap = hashMap.put(key, LinkedValue(value))
8384
return PersistentOrderedMap(key, key, newMap)
8485
}
8586

86-
val links = map[key]
87+
val links = hashMap[key]
8788
if (links != null) {
8889
if (links.value == value) {
8990
return this
9091
}
91-
val newMap = map.put(key, links.withValue(value))
92+
val newMap = hashMap.put(key, links.withValue(value))
9293
return PersistentOrderedMap(firstKey, lastKey, newMap)
9394
}
9495

95-
val lastLink = map[lastKey]!!
96-
// assert(lastLink.next === EndOfLink)
97-
val newMap = map
98-
.put(lastKey as K, lastLink.withNext(key))
96+
@Suppress("UNCHECKED_CAST")
97+
val lastKey = lastKey as K
98+
val lastLink = hashMap[lastKey]!!
99+
// assert(!lastLink.hasNext)
100+
val newMap = hashMap
101+
.put(lastKey, lastLink.withNext(key))
99102
.put(key, lastLink.putNextLink(value, lastKey))
100103
return PersistentOrderedMap(firstKey, key, newMap)
101104
}
102105

103106
override fun remove(key: K): PersistentOrderedMap<K, V> {
104-
val links = map[key] ?: return this
107+
val links = hashMap[key] ?: return this
105108

106-
var newMap = map.remove(key)
107-
if (links.previous !== EndOfLink) {
109+
var newMap = hashMap.remove(key)
110+
if (links.hasPrevious) {
108111
val previousLinks = newMap[links.previous]!!
109112
// assert(previousLinks.next == key)
113+
@Suppress("UNCHECKED_CAST")
110114
newMap = newMap.put(links.previous as K, previousLinks.withNext(links.next))
111115
}
112-
if (links.next !== EndOfLink) {
116+
if (links.hasNext) {
113117
val nextLinks = newMap[links.next]!!
114118
// assert(nextLinks.previous == key)
119+
@Suppress("UNCHECKED_CAST")
115120
newMap = newMap.put(links.next as K, nextLinks.withPrevious(links.previous))
116121
}
117122

118-
val newFirstKey = if (links.previous === EndOfLink) links.next else firstKey
119-
val newLastKey = if (links.next === EndOfLink) links.previous else lastKey
123+
val newFirstKey = if (!links.hasPrevious) links.next else firstKey
124+
val newLastKey = if (!links.hasNext) links.previous else lastKey
120125
return PersistentOrderedMap(newFirstKey, newLastKey, newMap)
121126
}
122127

123128
override fun remove(key: K, value: @UnsafeVariance V): PersistentOrderedMap<K, V> {
124-
val links = map[key] ?: return this
129+
val links = hashMap[key] ?: return this
125130
return if (links.value == value) this.remove(key) else this
126131
}
127132

@@ -138,7 +143,8 @@ internal class PersistentOrderedMap<K, V>(internal val firstKey: Any?,
138143
}
139144

140145
internal companion object {
141-
private val EMPTY = PersistentOrderedMap<Nothing, Nothing>(EndOfLink, EndOfLink, PersistentHashMap.emptyOf())
146+
private val EMPTY = PersistentOrderedMap<Nothing, Nothing>(EndOfChain, EndOfChain, PersistentHashMap.emptyOf<Nothing, LinkedValue<Nothing>>())
147+
@Suppress("UNCHECKED_CAST")
142148
internal fun <K, V> emptyOf(): PersistentOrderedMap<K, V> = EMPTY as PersistentOrderedMap<K, V>
143149
}
144150
}

kotlinx-collections-immutable/src/main/kotlin/kotlinx/collections/immutable/implementations/persistentOrderedMap/PersistentOrderedMapBuilder.kt

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,22 @@ import kotlinx.collections.immutable.PersistentMap
2020

2121
internal class PersistentOrderedMapBuilder<K, V>(private var map: PersistentOrderedMap<K, V>) : AbstractMutableMap<K, V>(), PersistentMap.Builder<K, V> {
2222
internal var firstKey = map.firstKey
23+
private set
24+
2325
private var lastKey = map.lastKey
24-
internal val mapBuilder = map.map.builder()
2526

26-
override val size: Int
27-
get() = mapBuilder.size
27+
internal val hashMapBuilder = map.hashMap.builder()
28+
29+
override val size: Int get() = hashMapBuilder.size
2830

2931
override fun build(): PersistentMap<K, V> {
30-
val newMap = mapBuilder.build()
31-
map = if (newMap === map.map) {
32+
val newHashMap = hashMapBuilder.build()
33+
map = if (newHashMap === map.hashMap) {
3234
assert(firstKey === map.firstKey)
3335
assert(lastKey === map.lastKey)
3436
map
3537
} else {
36-
PersistentOrderedMap(firstKey, lastKey, newMap)
38+
PersistentOrderedMap(firstKey, lastKey, newHashMap)
3739
}
3840
return map
3941
}
@@ -53,53 +55,53 @@ internal class PersistentOrderedMapBuilder<K, V>(private var map: PersistentOrde
5355
return PersistentOrderedMapBuilderValues(this)
5456
}
5557

56-
override fun containsKey(key: K): Boolean {
57-
return mapBuilder.containsKey(key)
58-
}
58+
override fun containsKey(key: K): Boolean = hashMapBuilder.containsKey(key)
5959

60-
override fun get(key: K): V? {
61-
return mapBuilder[key]?.value
62-
}
60+
override fun get(key: K): V? = hashMapBuilder[key]?.value
6361

6462
override fun put(key: K, value: @UnsafeVariance V): V? {
65-
val links = mapBuilder[key]
63+
val links = hashMapBuilder[key]
6664
if (links != null) {
6765
if (links.value === value) {
6866
return value
6967
}
70-
mapBuilder[key] = links.withValue(value)
68+
hashMapBuilder[key] = links.withValue(value)
7169
return links.value
7270
}
7371

7472
if (isEmpty()) { // isEmpty
7573
firstKey = key
7674
lastKey = key
77-
mapBuilder[key] = LinkedValue(value)
75+
hashMapBuilder[key] = LinkedValue(value)
7876
return null
7977
}
80-
val lastLink = mapBuilder[lastKey]!!
81-
assert(lastLink.next == EndOfLink)
82-
83-
mapBuilder[lastKey as K] = lastLink.withNext(key)
84-
mapBuilder[key] = lastLink.putNextLink(value, lastKey)
85-
lastKey = key
78+
@Suppress("UNCHECKED_CAST")
79+
val lastKey = lastKey as K
80+
val lastLink = hashMapBuilder[lastKey]!!
81+
assert(!lastLink.hasNext)
82+
83+
hashMapBuilder[lastKey] = lastLink.withNext(key)
84+
hashMapBuilder[key] = lastLink.putNextLink(value, lastKey)
85+
this.lastKey = key
8686
return null
8787
}
8888

8989
override fun remove(key: K): V? {
90-
val links = mapBuilder.remove(key) ?: return null
90+
val links = hashMapBuilder.remove(key) ?: return null
9191

92-
if (links.previous !== EndOfLink) {
93-
val previousLinks = mapBuilder[links.previous]!!
92+
if (links.hasPrevious) {
93+
val previousLinks = hashMapBuilder[links.previous]!!
9494
// assert(previousLinks.next == key)
95-
mapBuilder[links.previous as K] = previousLinks.withNext(links.next)
95+
@Suppress("UNCHECKED_CAST")
96+
hashMapBuilder[links.previous as K] = previousLinks.withNext(links.next)
9697
} else {
9798
firstKey = links.next
9899
}
99-
if (links.next !== EndOfLink) {
100-
val nextLinks = mapBuilder[links.next]!!
100+
if (links.hasNext) {
101+
val nextLinks = hashMapBuilder[links.next]!!
101102
// assert(nextLinks.previous == key)
102-
mapBuilder[links.next as K] = nextLinks.withPrevious(links.previous)
103+
@Suppress("UNCHECKED_CAST")
104+
hashMapBuilder[links.next as K] = nextLinks.withPrevious(links.previous)
103105
} else {
104106
lastKey = links.previous
105107
}
@@ -108,7 +110,7 @@ internal class PersistentOrderedMapBuilder<K, V>(private var map: PersistentOrde
108110
}
109111

110112
fun remove(key: K, value: V): Boolean {
111-
val links = mapBuilder[key] ?: return false
113+
val links = hashMapBuilder[key] ?: return false
112114

113115
return if (links.value != value) {
114116
false
@@ -119,8 +121,8 @@ internal class PersistentOrderedMapBuilder<K, V>(private var map: PersistentOrde
119121
}
120122

121123
override fun clear() {
122-
mapBuilder.clear()
123-
firstKey = EndOfLink
124-
lastKey = EndOfLink
124+
hashMapBuilder.clear()
125+
firstKey = EndOfChain
126+
lastKey = EndOfChain
125127
}
126128
}

kotlinx-collections-immutable/src/main/kotlin/kotlinx/collections/immutable/implementations/persistentOrderedMap/PersistentOrderedMapBuilderContentIterators.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ internal open class PersistentOrderedMapBuilderLinksIterator<K, V>(
2323
internal val builder: PersistentOrderedMapBuilder<K, V>
2424
) : MutableIterator<LinkedValue<V>> {
2525

26-
internal var lastIteratedKey: Any? = EndOfLink
26+
internal var lastIteratedKey: Any? = EndOfChain
2727
private var nextWasInvoked = false
28-
private var expectedModCount = builder.mapBuilder.modCount
28+
private var expectedModCount = builder.hashMapBuilder.modCount
2929
internal var index = 0
3030

3131
override fun hasNext(): Boolean {
@@ -38,7 +38,7 @@ internal open class PersistentOrderedMapBuilderLinksIterator<K, V>(
3838
lastIteratedKey = nextKey
3939
nextWasInvoked = true
4040
index++
41-
val result = builder.mapBuilder[nextKey]!!
41+
val result = builder.hashMapBuilder[nextKey]!!
4242
nextKey = result.next
4343
return result
4444
}
@@ -48,7 +48,7 @@ internal open class PersistentOrderedMapBuilderLinksIterator<K, V>(
4848
builder.remove(lastIteratedKey)
4949
lastIteratedKey = null
5050
nextWasInvoked = false
51-
expectedModCount = builder.mapBuilder.modCount
51+
expectedModCount = builder.hashMapBuilder.modCount
5252
index--
5353
}
5454

@@ -63,7 +63,7 @@ internal open class PersistentOrderedMapBuilderLinksIterator<K, V>(
6363
}
6464

6565
private fun checkForComodification() {
66-
if (builder.mapBuilder.modCount != expectedModCount)
66+
if (builder.hashMapBuilder.modCount != expectedModCount)
6767
throw ConcurrentModificationException()
6868
}
6969
}
@@ -77,7 +77,7 @@ internal class PersistentOrderedMapBuilderEntriesIterator<K, V>(map: PersistentO
7777

7878
override fun next(): MutableMap.MutableEntry<K, V> {
7979
val links = internal.next()
80-
return MutableMapEntry(internal.builder.mapBuilder, internal.lastIteratedKey as K, links)
80+
return MutableMapEntry(internal.builder.hashMapBuilder, internal.lastIteratedKey as K, links)
8181
}
8282

8383
override fun remove() {

kotlinx-collections-immutable/src/main/kotlin/kotlinx/collections/immutable/implementations/persistentOrderedMap/PersistentOrderedMapContentIterators.kt

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,56 +18,60 @@ package kotlinx.collections.immutable.implementations.persistentOrderedMap
1818

1919
import kotlinx.collections.immutable.implementations.immutableMap.MapEntry
2020

21-
internal open class PersistentOrderedMapLinksIterator<K, V>(internal var nextKey: Any?,
22-
internal val map: Map<K, LinkedValue<V>>) : Iterator<LinkedValue<V>> {
21+
internal open class PersistentOrderedMapLinksIterator<K, V>(
22+
internal var nextKey: Any?,
23+
private val hashMap: Map<K, LinkedValue<V>>
24+
) : Iterator<LinkedValue<V>> {
2325
internal var index = 0
2426

2527
override fun hasNext(): Boolean {
26-
return index < map.size
28+
return index < hashMap.size
2729
}
2830

2931
override fun next(): LinkedValue<V> {
3032
if (!hasNext()) {
3133
throw NoSuchElementException()
3234
}
33-
val result = map[nextKey]!!
35+
val result = hashMap[nextKey]!!
3436
index++
3537
nextKey = result.next
3638
return result
3739
}
3840

3941
}
4042

41-
internal class PersistentOrderedMapEntriesIterator<out K, out V>(map: PersistentOrderedMap<K, V>): Iterator<Map.Entry<K, V>> {
42-
private val internal = PersistentOrderedMapLinksIterator(map.firstKey, map.map)
43+
internal class PersistentOrderedMapEntriesIterator<out K, out V>(map: PersistentOrderedMap<K, V>) : Iterator<Map.Entry<K, V>> {
44+
private val internal = PersistentOrderedMapLinksIterator(map.firstKey, map.hashMap)
4345

4446
override fun hasNext(): Boolean {
4547
return internal.hasNext()
4648
}
4749

4850
override fun next(): Map.Entry<K, V> {
51+
@Suppress("UNCHECKED_CAST")
4952
val nextKey = internal.nextKey as K
5053
val nextValue = internal.next().value
5154
return MapEntry(nextKey, nextValue)
5255
}
5356
}
5457

55-
internal class PersistentOrderedMapKeysIterator<out K, out V>(map: PersistentOrderedMap<K, V>): Iterator<K> {
56-
private val internal = PersistentOrderedMapLinksIterator(map.firstKey, map.map)
58+
internal class PersistentOrderedMapKeysIterator<out K, out V>(map: PersistentOrderedMap<K, V>) : Iterator<K> {
59+
private val internal = PersistentOrderedMapLinksIterator(map.firstKey, map.hashMap)
5760

5861
override fun hasNext(): Boolean {
5962
return internal.hasNext()
6063
}
6164

6265
override fun next(): K {
66+
@Suppress("UNCHECKED_CAST")
6367
val nextKey = internal.nextKey as K
6468
internal.next()
6569
return nextKey
6670
}
6771
}
6872

69-
internal class PersistentOrderedMapValuesIterator<out K, out V>(map: PersistentOrderedMap<K, V>): Iterator<V> {
70-
private val internal = PersistentOrderedMapLinksIterator(map.firstKey, map.map)
73+
internal class PersistentOrderedMapValuesIterator<out K, out V>(map: PersistentOrderedMap<K, V>) : Iterator<V> {
74+
private val internal = PersistentOrderedMapLinksIterator(map.firstKey, map.hashMap)
7175

7276
override fun hasNext(): Boolean {
7377
return internal.hasNext()

0 commit comments

Comments
 (0)