Skip to content

Commit 9de2bf8

Browse files
Abdukodiri KurbonzodaAbduqodiri Qurbonzoda
authored andcommitted
Implement PersistentOrderedSet
1 parent 3a10997 commit 9de2bf8

File tree

8 files changed

+275
-9
lines changed

8 files changed

+275
-9
lines changed

kotlinx-collections-immutable/src/main/kotlin/kotlinx/collections/immutable/extensions.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import kotlinx.collections.immutable.implementations.immutableMap.PersistentHash
2323
import kotlinx.collections.immutable.implementations.immutableMap.PersistentHashMapBuilder
2424
import kotlinx.collections.immutable.implementations.immutableSet.PersistentHashSet
2525
import kotlinx.collections.immutable.implementations.immutableSet.PersistentHashSetBuilder
26+
import kotlinx.collections.immutable.implementations.persistentOrderedSet.PersistentOrderedSet
2627

2728
//@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
2829
//inline fun <T> @kotlin.internal.Exact ImmutableCollection<T>.mutate(mutator: (MutableCollection<T>) -> Unit): ImmutableCollection<T> = builder().apply(mutator).build()
@@ -129,8 +130,8 @@ public operator fun <K, V> PersistentMap<out K, V>.minus(keys: Sequence<K>): Per
129130
fun <E> persistentListOf(vararg elements: E): PersistentList<E> = persistentVectorOf<E>().addAll(elements.asList())
130131
fun <E> persistentListOf(): PersistentList<E> = persistentVectorOf()
131132

132-
fun <E> persistentSetOf(vararg elements: E): PersistentSet<E> = ImmutableOrderedSet.emptyOf<E>().addAll(elements.asList())
133-
fun <E> persistentSetOf(): PersistentSet<E> = ImmutableOrderedSet.emptyOf<E>()
133+
fun <E> persistentSetOf(vararg elements: E): PersistentSet<E> = PersistentOrderedSet.emptyOf<E>().addAll(elements.asList())
134+
fun <E> persistentSetOf(): PersistentSet<E> = PersistentOrderedSet.emptyOf<E>()
134135

135136
fun <E> persistentHashSetOf(vararg elements: E): PersistentSet<E> = PersistentHashSet.emptyOf<E>().addAll(elements.asList())
136137

kotlinx-collections-immutable/src/main/kotlin/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ internal class PersistentHashMap<K, V>(internal val node: TrieNode<K, V>,
6262
return node.get(keyHash, key, 0)
6363
}
6464

65-
override fun put(key: K, value: @UnsafeVariance V): PersistentMap<K, V> {
65+
override fun put(key: K, value: @UnsafeVariance V): PersistentHashMap<K, V> {
6666
val keyHash = key?.hashCode() ?: NULL_HASH_CODE
6767
val modification = ModificationWrapper()
6868
val newNode = node.put(keyHash, key, value, 0, modification)
@@ -71,15 +71,15 @@ internal class PersistentHashMap<K, V>(internal val node: TrieNode<K, V>,
7171
return PersistentHashMap(newNode, size + sizeDelta)
7272
}
7373

74-
override fun remove(key: K): PersistentMap<K, V> {
74+
override fun remove(key: K): PersistentHashMap<K, V> {
7575
val keyHash = key?.hashCode() ?: NULL_HASH_CODE
7676
val newNode = node.remove(keyHash, key, 0)
7777
if (node === newNode) { return this }
7878
if (newNode == null) { return PersistentHashMap.emptyOf() }
7979
return PersistentHashMap(newNode, size - 1)
8080
}
8181

82-
override fun remove(key: K, value: @UnsafeVariance V): PersistentMap<K, V> {
82+
override fun remove(key: K, value: @UnsafeVariance V): PersistentHashMap<K, V> {
8383
val keyHash = key?.hashCode() ?: NULL_HASH_CODE
8484
val newNode = node.remove(keyHash, key, value, 0)
8585
if (node === newNode) { return this }
@@ -95,12 +95,12 @@ internal class PersistentHashMap<K, V>(internal val node: TrieNode<K, V>,
9595
return PersistentHashMap.emptyOf()
9696
}
9797

98-
override fun builder(): PersistentMap.Builder<K, @UnsafeVariance V> {
98+
override fun builder(): PersistentHashMapBuilder<K, V> {
9999
return PersistentHashMapBuilder(this)
100100
}
101101

102102
internal companion object {
103103
private val EMPTY = PersistentHashMap(TrieNode.EMPTY, 0)
104-
internal fun <K, V> emptyOf(): PersistentMap<K, V> = EMPTY as PersistentMap<K, V>
104+
internal fun <K, V> emptyOf(): PersistentHashMap<K, V> = EMPTY as PersistentHashMap<K, V>
105105
}
106106
}

kotlinx-collections-immutable/src/main/kotlin/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ internal class PersistentHashMapBuilder<K, V>(private var map: PersistentHashMap
2626
internal var operationResult: V? = null
2727
override var size = map.size
2828

29-
override fun build(): PersistentMap<K, V> {
29+
override fun build(): PersistentHashMap<K, V> {
3030
map = if (node === map.node) {
3131
map
3232
} else {

kotlinx-collections-immutable/src/main/kotlin/kotlinx/collections/immutable/implementations/immutableSet/PersistentHashSetBuilder.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ package kotlinx.collections.immutable.implementations.immutableSet
1818

1919
import kotlinx.collections.immutable.PersistentSet
2020

21-
class Marker
21+
internal class Marker
2222

2323
internal class PersistentHashSetBuilder<E>(private var set: PersistentHashSet<E>) : AbstractMutableSet<E>(), PersistentSet.Builder<E> {
2424
internal var marker = Marker()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright 2016-2018 JetBrains s.r.o.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package kotlinx.collections.immutable.implementations.persistentOrderedSet
18+
19+
import kotlinx.collections.immutable.PersistentSet
20+
import kotlinx.collections.immutable.implementations.immutableMap.PersistentHashMap
21+
import kotlinx.collections.immutable.mutate
22+
23+
internal class Links<out E>(val previous: E?, val next: E?)
24+
25+
internal class PersistentOrderedSet<E>(internal val firstElement: E?,
26+
internal val lastElement: E?,
27+
internal val map: PersistentHashMap<E, Links<E>>): AbstractSet<E>(), PersistentSet<E> {
28+
29+
override val size: Int
30+
get() = map.size
31+
32+
override fun contains(element: E): Boolean {
33+
return map.containsKey(element)
34+
}
35+
36+
override fun add(element: E): PersistentSet<E> {
37+
if (map.containsKey(element)) {
38+
return this
39+
}
40+
if (lastElement == null) { // isEmpty
41+
val newMap = map.put(element, Links<E>(null, null))
42+
return PersistentOrderedSet(element, element, newMap)
43+
}
44+
val oldLinks = map[lastElement]!!
45+
assert(oldLinks.next == null)
46+
val newLinks = Links(oldLinks.previous, element)
47+
val newMap = map.put(lastElement, newLinks).put(element, Links(lastElement, null))
48+
return PersistentOrderedSet(firstElement, element, newMap)
49+
}
50+
51+
override fun addAll(elements: Collection<E>): PersistentSet<E> {
52+
return this.mutate { it.addAll(elements) }
53+
}
54+
55+
override fun remove(element: E): PersistentSet<E> {
56+
val links = map[element] ?: return this
57+
58+
var newMap = map.remove(element)
59+
if (links.previous != null) {
60+
val previousLinks = newMap[links.previous]!!
61+
assert(previousLinks.next == element)
62+
newMap = newMap.put(links.previous, Links(previousLinks.previous, links.next))
63+
}
64+
if (links.next != null) {
65+
val nextLinks = newMap[links.next]!!
66+
assert(nextLinks.previous == element)
67+
newMap = newMap.put(links.next, Links(links.previous, nextLinks.next))
68+
}
69+
val newFirstElement = if (element == firstElement) links.next else firstElement
70+
val newLastElement = if (element == lastElement) links.previous else lastElement
71+
return PersistentOrderedSet(newFirstElement, newLastElement, newMap)
72+
}
73+
74+
override fun removeAll(elements: Collection<E>): PersistentSet<E> {
75+
return mutate { it.removeAll(elements) }
76+
}
77+
78+
override fun removeAll(predicate: (E) -> Boolean): PersistentSet<E> {
79+
return mutate { it.removeAll(predicate) }
80+
}
81+
82+
override fun clear(): PersistentSet<E> {
83+
return PersistentOrderedSet.emptyOf()
84+
}
85+
86+
override fun iterator(): Iterator<E> {
87+
return PersistentOrderedSetIterator(firstElement, map)
88+
}
89+
90+
override fun builder(): PersistentSet.Builder<E> {
91+
return PersistentOrderedSetBuilder(this)
92+
}
93+
94+
internal companion object {
95+
private val EMPTY = PersistentOrderedSet(null, null, PersistentHashMap.emptyOf())
96+
internal fun <E> emptyOf(): PersistentSet<E> = EMPTY
97+
}
98+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Copyright 2016-2018 JetBrains s.r.o.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package kotlinx.collections.immutable.implementations.persistentOrderedSet
18+
19+
import kotlinx.collections.immutable.PersistentSet
20+
21+
internal class PersistentOrderedSetBuilder<E>(private var set: PersistentOrderedSet<E>) : AbstractMutableSet<E>(), PersistentSet.Builder<E> {
22+
internal var firstElement = set.firstElement
23+
private var lastElement = set.lastElement
24+
internal val mapBuilder = set.map.builder()
25+
26+
override val size: Int
27+
get() = mapBuilder.size
28+
29+
override fun build(): PersistentSet<E> {
30+
val newMap = mapBuilder.build()
31+
set = if (newMap === set.map) {
32+
assert(firstElement === set.firstElement)
33+
assert(lastElement === set.lastElement)
34+
set
35+
} else {
36+
PersistentOrderedSet(firstElement, lastElement, newMap)
37+
}
38+
return set
39+
}
40+
41+
override fun contains(element: E): Boolean {
42+
return mapBuilder.containsKey(element)
43+
}
44+
45+
override fun add(element: E): Boolean {
46+
if (mapBuilder.containsKey(element)) {
47+
return false
48+
}
49+
if (lastElement == null) { // isEmpty
50+
firstElement = element
51+
lastElement = element
52+
mapBuilder[element] = Links<E>(null, null)
53+
return true
54+
}
55+
val oldLinks = mapBuilder[lastElement!!]!!
56+
assert(oldLinks.next == null)
57+
val newLinks = Links(oldLinks.previous, element)
58+
59+
mapBuilder[lastElement!!] = newLinks
60+
mapBuilder[element] = Links(lastElement, null)
61+
lastElement = element
62+
return true
63+
}
64+
65+
override fun remove(element: E): Boolean {
66+
val links = mapBuilder.remove(element) ?: return false
67+
68+
if (links.previous != null) {
69+
val previousLinks = mapBuilder[links.previous]!!
70+
assert(previousLinks.next == element)
71+
mapBuilder[links.previous] = Links(previousLinks.previous, links.next)
72+
}
73+
if (links.next != null) {
74+
val nextLinks = mapBuilder[links.next]!!
75+
assert(nextLinks.previous == element)
76+
mapBuilder[links.next] = Links(links.previous, nextLinks.next)
77+
}
78+
firstElement = if (element == firstElement) links.next else firstElement
79+
lastElement = if (element == lastElement) links.previous else lastElement
80+
return true
81+
}
82+
83+
override fun clear() {
84+
mapBuilder.clear()
85+
firstElement = null
86+
lastElement = null
87+
}
88+
89+
override fun iterator(): MutableIterator<E> {
90+
return PersistentOrderedSetMutableIterator(this)
91+
}
92+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2016-2018 JetBrains s.r.o.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package kotlinx.collections.immutable.implementations.persistentOrderedSet
18+
19+
internal open class PersistentOrderedSetIterator<E>(private var nextElement: E?,
20+
internal val map: Map<E, Links<E>>) : Iterator<E> {
21+
internal var index = 0
22+
23+
override fun hasNext(): Boolean {
24+
return index < map.size
25+
}
26+
27+
override fun next(): E {
28+
assert(hasNext())
29+
val result = nextElement as E
30+
index++
31+
nextElement = map[result]!!.next
32+
return result
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2016-2018 JetBrains s.r.o.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package kotlinx.collections.immutable.implementations.persistentOrderedSet
18+
19+
internal class PersistentOrderedSetMutableIterator<E>(private val builder: PersistentOrderedSetBuilder<E>)
20+
: PersistentOrderedSetIterator<E>(builder.firstElement, builder.mapBuilder), MutableIterator<E> {
21+
22+
var lastReturned: E? = null
23+
var nextWasInvoked = false
24+
25+
override fun next(): E {
26+
val next = super.next()
27+
lastReturned = next
28+
nextWasInvoked = true
29+
return next
30+
}
31+
32+
override fun remove() {
33+
if (!nextWasInvoked) {
34+
throw NoSuchElementException()
35+
}
36+
builder.remove(lastReturned)
37+
index--
38+
lastReturned = null
39+
nextWasInvoked = false
40+
}
41+
}

0 commit comments

Comments
 (0)