@@ -2,23 +2,32 @@ package kotlinx.collections.immutable
2
2
3
3
import org.pcollections.HashTreePMap
4
4
import org.pcollections.PMap
5
- import org.pcollections.PVector
6
- import org.pcollections.TreePVector
7
- import java.util.*
5
+ import java.util.ConcurrentModificationException
8
6
9
7
10
- internal class ImmutableOrderedMap <K , out V > private constructor(private val impl : PMap <K , V >, private val order : PVector <Map .Entry <K ,V >>) : ImmutableMap<K, V> {
8
+ internal class ImmutableOrderedMap <K , out V > private constructor(private val impl : PMap <K , LinkedEntry <K , V >>) : ImmutableMap<K, V>, AbstractMap<K, V>() {
9
+ // TODO: Keep reference to first/last entry
10
+
11
+ protected class LinkedEntry <out K , out V >(val key : K , val value : @UnsafeVariance V , val prevKey : Any? , val nextKey : Any? ) {
12
+ // has referential equality/hashCode
13
+
14
+ fun copy (value : @UnsafeVariance V = this.value, prevKey : Any? = this.prevKey, nextKey : Any? = this.nextKey) =
15
+ LinkedEntry (key, value, prevKey, nextKey)
16
+
17
+ // had to separate map entry implementations because of conflicting equality/hashCode
18
+ inner class MapEntry : AbstractImmutableMap .AbstractImmutableEntry <K , V >() {
19
+ override val key: K get() = this @LinkedEntry.key
20
+ override val value: V get() = this @LinkedEntry.value
21
+ }
22
+ val mapEntry = MapEntry ()
23
+ }
11
24
12
25
override val size: Int get() = impl.size
13
26
override fun isEmpty (): Boolean = impl.isEmpty()
14
27
override fun containsKey (key : K ): Boolean = impl.containsKey(key)
15
- override fun containsValue (value : @UnsafeVariance V ): Boolean = impl.containsValue( value)
28
+ override fun containsValue (value : @UnsafeVariance V ): Boolean = impl.values.any { it. value == value }
16
29
17
- override fun get (key : K ): V ? = impl.get(key)
18
-
19
- override fun equals (other : Any? ): Boolean = impl.equals(other)
20
- override fun hashCode (): Int = impl.hashCode()
21
- override fun toString (): String = impl.toString()
30
+ override fun get (key : K ): V ? = impl[key]?.value
22
31
23
32
24
33
// should it be immutable set/collection or just read-only?
@@ -34,50 +43,43 @@ internal class ImmutableOrderedMap<K, out V> private constructor(private val imp
34
43
final override val entries: Set <Map .Entry <K , V >> get() = _entries ? : createEntries().apply { _entries = this }
35
44
private fun createEntries (): Set <Map .Entry <K , V >> = OrderedEntrySet ()
36
45
37
- override fun put (key : K , value : @UnsafeVariance V ): ImmutableMap <K , V > = wrap(impl.plus( key, value)) { order.addOrReplace( key, value) }
46
+ override fun put (key : K , value : @UnsafeVariance V ): ImmutableMap <K , V > = wrap(impl.putEntry(impl[ key], key, value))
38
47
override fun putAll (m : Map <out K , @UnsafeVariance V >): ImmutableMap <K , V > {
39
48
var newImpl = impl
40
- var newOrder = order
41
- for ((k, v) in m) {
42
- newImpl.plus(k, v).let { if (it != newImpl) {
43
- newImpl = it
44
- newOrder = newOrder.addOrReplace(k, v)
45
- }}
46
- }
47
- return wrap(newImpl) { newOrder }
49
+ for ((k, v) in m)
50
+ newImpl = newImpl.putEntry(newImpl[k], k, v)
51
+
52
+ return wrap(newImpl)
48
53
}
49
- override fun remove (key : K ): ImmutableMap <K , V > = wrap(impl.minus(key), { order.minus(order.indexOfFirst { it.key == key })})
54
+ override fun remove (key : K ): ImmutableMap <K , V > = wrap(impl.removeLinked(key))
55
+
50
56
override fun remove (key : K , value : @UnsafeVariance V ): ImmutableMap <K , V >
51
57
= if (! impl.contains(key, value)) this else remove(key)
52
58
53
59
override fun clear (): ImmutableMap <K , V > = emptyOf()
54
60
55
- override fun builder (): ImmutableMap .Builder <K , @UnsafeVariance V > = Builder (this , impl, order )
61
+ override fun builder (): ImmutableMap .Builder <K , @UnsafeVariance V > = Builder (this , impl)
56
62
57
- private fun entry (key : K , value : @UnsafeVariance V ): Map .Entry <K , V > = AbstractMap .SimpleEntry (key, value)
58
-
59
- protected fun wrap (impl : PMap <K , @UnsafeVariance V >, order : (PVector <Map .Entry <K , @UnsafeVariance V >>) -> PVector <Map .Entry <K , @UnsafeVariance V >>): ImmutableOrderedMap <K , V > {
60
- return if (impl == = this .impl) this else ImmutableOrderedMap (impl, order(this .order))
63
+ protected fun wrap (impl : PMap <K , LinkedEntry <K , @UnsafeVariance V >>): ImmutableOrderedMap <K , V > {
64
+ return if (impl == = this .impl) this else ImmutableOrderedMap (impl)
61
65
}
62
66
63
67
64
- protected class Builder <K , V >(protected var value : ImmutableOrderedMap <K , V >, protected var impl : PMap <K , V >, protected var order : PVector < Map . Entry < K , V >>) : ImmutableMap.Builder<K, V>, AbstractMap <K, V>() {
65
- override fun build (): ImmutableMap <K , V > = value.wrap(impl, { order } ).apply { value = this }
68
+ protected class Builder <K , V >(protected var value : ImmutableOrderedMap <K , V >, protected var impl : PMap <K , LinkedEntry < K , V >>) : ImmutableMap.Builder<K, V>, AbstractMutableMap <K, V>() {
69
+ override fun build (): ImmutableMap <K , V > = value.wrap(impl).apply { value = this }
66
70
67
71
override val size: Int get() = impl.size
68
72
override fun isEmpty (): Boolean = impl.isEmpty()
69
73
override fun containsKey (key : K ): Boolean = impl.containsKey(key)
70
- override fun containsValue (value : @UnsafeVariance V ): Boolean = impl.containsValue(value)
71
-
72
- override fun get (key : K ): V ? = impl.get(key)
74
+ override fun containsValue (value : @UnsafeVariance V ): Boolean = impl.values.any { it.value == value }
73
75
74
- override fun equals (other : Any? ): Boolean = impl.equals(other)
75
- override fun hashCode (): Int = impl.hashCode()
76
- override fun toString (): String = impl.toString()
76
+ override fun get (key : K ): V ? = impl.get(key)?.value
77
77
78
78
private var entrySet: MutableSet <MutableMap .MutableEntry <K , V >>? = null
79
79
override val entries: MutableSet <MutableMap .MutableEntry <K , V >>
80
- get() = entrySet ? : object : MutableSet <MutableMap .MutableEntry <K , V >>, AbstractSet <MutableMap .MutableEntry <K , V >>() {
80
+ get() = entrySet ? : object : AbstractMutableSet <MutableMap .MutableEntry <K , V >>() {
81
+ override fun add (element : MutableMap .MutableEntry <K , V >): Boolean = throw UnsupportedOperationException ()
82
+
81
83
override val size: Int get() = impl.size
82
84
override fun isEmpty (): Boolean = impl.isEmpty()
83
85
override fun clear () = this @Builder.clear()
@@ -95,15 +97,14 @@ internal class ImmutableOrderedMap<K, out V> private constructor(private val imp
95
97
96
98
override fun iterator () = object : MutableIterator <MutableMap .MutableEntry <K , V >> {
97
99
private var snapshot = impl
98
- private val iterator = order.iterator()
99
- private var entry: Map .Entry <K ,V >? = null
100
+ private var entry: LinkedEntry <K ,V >? = impl.firstEntry()
100
101
101
- override fun hasNext (): Boolean = iterator.hasNext()
102
+ override fun hasNext (): Boolean = entry != null
102
103
override fun next (): MutableMap .MutableEntry <K , V > {
103
104
checkForComodification()
104
- val entry = iterator.next ()
105
- this .entry = entry
106
- return object : MutableMap .MutableEntry <K , V >, Map .Entry <K , V > by entry {
105
+ val entry = this .entry ? : throw NoSuchElementException ()
106
+ this .entry = snapshot[ entry.nextKey]
107
+ return object : MutableMap .MutableEntry <K , V >, Map .Entry <K , V > by entry.mapEntry {
107
108
override fun setValue (newValue : V ): V {
108
109
checkForComodification()
109
110
val oldValue = put(entry.key, newValue) as V
@@ -127,35 +128,32 @@ internal class ImmutableOrderedMap<K, out V> private constructor(private val imp
127
128
}
128
129
}.apply { entrySet = this }
129
130
130
- // by AbstractMap
131
- // override val keys: MutableSet<K>
132
- // override val values: MutableCollection<V>
133
-
134
- override val values: MutableCollection <V >
135
- get() = super .values
136
- override val keys: MutableSet <K >
137
- get() = super .keys
138
131
139
132
override fun clear () {
140
- mutate(HashTreePMap .empty(), { TreePVector .empty() } )
133
+ mutate(HashTreePMap .empty())
141
134
}
142
135
143
- override fun put (key : K , value : V ): V ? =
144
- get(key).apply {
145
- mutate(impl.plus(key, value), { order.addOrReplace(key, value) })
146
- }
136
+ override fun put (key : K , value : V ): V ? {
137
+ val entry = impl[key]
138
+
139
+ mutate(impl.putEntry(entry, key, value))
140
+
141
+ return entry?.value
142
+ }
147
143
148
144
override fun putAll (from : Map <out K , V >) {
149
145
for ((k, v) in from) put(k, v)
150
146
}
151
147
152
148
153
- override fun remove (key : K ): V ?
154
- = get(key).apply { mutate(impl.minus(key), { it.minus(it.indexOfFirst { it.key == key })}) }
149
+ override fun remove (key : K ): V ? {
150
+ val entry = impl[key] ? : return null
151
+ mutate(impl.removeEntry(entry))
152
+ return entry.value
153
+ }
155
154
156
- protected inline fun mutate (newValue : PMap <K , V >, orderOperation : ( PVector < Map . Entry < K , V >>) -> ( PVector < Map . Entry < K , V >>) ): Boolean {
155
+ protected inline fun mutate (newValue : PMap <K , LinkedEntry < K , V >>): Boolean {
157
156
if (newValue != = impl) {
158
- order = orderOperation(order)
159
157
impl = newValue
160
158
return true
161
159
}
@@ -165,46 +163,92 @@ internal class ImmutableOrderedMap<K, out V> private constructor(private val imp
165
163
}
166
164
167
165
companion object {
168
- private val EMPTY = ImmutableOrderedMap (HashTreePMap .empty<Any ?, Nothing >(), TreePVector .empty())
166
+ private val EMPTY = ImmutableOrderedMap (HashTreePMap .empty<Any ?, LinkedEntry <Any ?, Nothing >>())
167
+
168
+ private val TERMINATOR = Any ()
169
+
170
+ private fun <K , V > PMap <K , LinkedEntry <K , V >>.contains (key : K , value : @UnsafeVariance V ): Boolean
171
+ = this [key]?.let { entry -> entry.value == value } ? : false
172
+
173
+ private fun <K , V > PMap <K , LinkedEntry <K , V >>.removeLinked (key : K ): PMap <K , LinkedEntry <K , V >> {
174
+ val entry = this [key] ? : return this
175
+ return removeEntry(entry)
176
+ }
177
+
178
+ private fun <K , V > PMap <K , LinkedEntry <K , V >>.removeEntry (entry : LinkedEntry <K , V >): PMap <K , LinkedEntry <K , V >> {
179
+ val prevKey = entry.prevKey
180
+ val nextKey = entry.nextKey
181
+ var new = this .minus(entry.key)
182
+
183
+ if (prevKey != = TERMINATOR ) {
184
+ @Suppress(" UNCHECKED_CAST" )
185
+ val prevEntry = this [prevKey as K ]!!
186
+ val newPrevEntry = prevEntry.copy(nextKey = nextKey)
187
+ new = new.plus(newPrevEntry.key, newPrevEntry)
188
+ }
189
+ if (nextKey != = TERMINATOR ) {
190
+ @Suppress(" UNCHECKED_CAST" )
191
+ val nextEntry = this [nextKey as K ]!!
192
+ val newNextEntry = nextEntry.copy(prevKey = prevKey)
193
+ new = new.plus(newNextEntry.key, newNextEntry)
194
+ }
195
+ return new
196
+ }
197
+
198
+ private fun <K , V > PMap <K , LinkedEntry <K , V >>.putEntry (entry : LinkedEntry <K , V >? , key : K , value : V ): PMap <K , LinkedEntry <K , V >> {
199
+ if (entry != null ) {
200
+ return if (entry.value == value) this else this .plus(key, entry.copy(value = value))
201
+ }
202
+ val lastEntry = this .lastEntry()
203
+ if (lastEntry == null ) {
204
+ val newEntry = LinkedEntry (key, value, TERMINATOR , TERMINATOR )
205
+ return this .plus(key, newEntry)
206
+ } else {
207
+ val newEntry = LinkedEntry (key, value, lastEntry.key, TERMINATOR )
208
+ val newLastEntry = lastEntry.copy(nextKey = key)
209
+ return this .plus(lastEntry.key, newLastEntry).plus(key, newEntry)
210
+ }
211
+ }
212
+
213
+ private fun <K , V > PMap <K , LinkedEntry <K , V >>.firstEntry () = this .values.firstOrNull { it.prevKey == = TERMINATOR }
214
+ private fun <K , V > PMap <K , LinkedEntry <K , V >>.lastEntry () = this .values.firstOrNull { it.nextKey == = TERMINATOR }
215
+
169
216
170
217
@Suppress(" UNCHECKED_CAST" )
171
218
fun <K , V > emptyOf (): ImmutableOrderedMap <K , V > = EMPTY as ImmutableOrderedMap <K , V >
172
219
}
173
220
221
+ private val entrySequence = generateSequence(impl.firstEntry()) { e -> impl[e.nextKey] }
174
222
175
- private inner class OrderedEntrySet : Set <Map .Entry <K , V >> {
223
+ private inner class OrderedEntrySet : AbstractSet <Map .Entry <K , V >>() {
176
224
override val size: Int get() = impl.size
177
- override fun contains (element : Map .Entry <K , @UnsafeVariance V >): Boolean = impl.entries. contains(element)
178
- override fun containsAll (elements : Collection <Map .Entry <K , @UnsafeVariance V >>): Boolean = impl.entries.containsAll(elements)
225
+ override fun contains (element : Map .Entry <K , @UnsafeVariance V >): Boolean = impl.contains(element.key, element.value )
226
+ override fun containsAll (elements : Collection <Map .Entry <K , @UnsafeVariance V >>): Boolean = elements.all { (k, v) -> impl.contains(k, v) }
179
227
override fun isEmpty (): Boolean = impl.isEmpty()
180
- override fun iterator (): Iterator <Map .Entry <K , V >> = order.iterator()
228
+ private val mapped = entrySequence.map { it.mapEntry }
229
+ override fun iterator (): Iterator <Map .Entry <K , V >> = mapped.iterator()
181
230
}
182
231
183
- private inner class OrderedKeySet : Set <K > {
232
+ private inner class OrderedKeySet : AbstractSet <K >() {
184
233
override val size: Int get() = impl.size
185
234
override fun contains (element : K ): Boolean = impl.containsKey(element)
186
235
override fun containsAll (elements : Collection <K >): Boolean = impl.keys.containsAll(elements)
187
236
188
237
override fun isEmpty (): Boolean = impl.isEmpty()
189
238
190
- private val mapped = order.asSequence() .map { it.key }
239
+ private val mapped = entrySequence .map { it.key }
191
240
override fun iterator (): Iterator <K > = mapped.iterator()
192
241
}
193
242
194
- private inner class OrderedValueCollection : Collection <V > {
243
+ private inner class OrderedValueCollection : AbstractCollection <V >() {
195
244
override val size: Int get() = impl.size
196
- override fun contains (element : @UnsafeVariance V ): Boolean = impl. containsValue(element)
197
- override fun containsAll (elements : Collection <@UnsafeVariance V >): Boolean = impl.values.containsAll(elements)
245
+ override fun contains (element : @UnsafeVariance V ): Boolean = containsValue(element)
246
+ override fun containsAll (elements : Collection <@UnsafeVariance V >): Boolean = elements.all { v -> containsValue(v) }
198
247
override fun isEmpty (): Boolean = impl.isEmpty()
199
248
200
- private val mapped = order.asSequence() .map { it.value }
249
+ private val mapped = entrySequence .map { it.value }
201
250
override fun iterator (): Iterator <V > = mapped.iterator()
202
251
}
203
252
}
204
253
205
- private fun <K , V > PVector<Map.Entry <K , V >>.addOrReplace (key : K , value : V ): PVector <Map .Entry <K , V >> {
206
- val index = indexOfFirst { it.key == key }
207
- val entry = AbstractMap .SimpleEntry (key, value)
208
- return if (index >= 0 ) with (index, entry) else plus(entry)
209
- }
210
254
0 commit comments