Skip to content

Commit a1d250a

Browse files
popemattqurbonzoda
authored andcommitted
Avoid creating new PersistentList instance when adding all elements of an empty collection
1 parent 16bd411 commit a1d250a

File tree

4 files changed

+27
-0
lines changed

4 files changed

+27
-0
lines changed

core/commonMain/src/implementations/immutableList/SmallPersistentVector.kt

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ internal class SmallPersistentVector<E>(private val buffer: Array<Any?>) : Immut
3636
}
3737

3838
override fun addAll(elements: Collection<E>): PersistentList<E> {
39+
if (elements.isEmpty()) return this
3940
if (size + elements.size <= MAX_BUFFER_SIZE) {
4041
val newBuffer = buffer.copyOf(size + elements.size)
4142
// TODO: investigate performance of elements.toArray + copyInto
@@ -80,6 +81,7 @@ internal class SmallPersistentVector<E>(private val buffer: Array<Any?>) : Immut
8081

8182
override fun addAll(index: Int, c: Collection<E>): PersistentList<E> {
8283
checkPositionIndex(index, size)
84+
if (c.isEmpty()) return this
8385
if (size + c.size <= MAX_BUFFER_SIZE) {
8486
val newBuffer = bufferOfSize(size + c.size)
8587
buffer.copyInto(newBuffer, endIndex = index)

core/commonTest/src/contract/list/ImmutableListTest.kt

+10
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ class ImmutableListTest {
6868
compareLists(list, immList)
6969
}
7070

71+
@Test fun emptyListToPersistentList() {
72+
val empty = emptyList<Int>()
73+
val emptyPersistent = empty.toPersistentList()
74+
75+
assertSame(emptyPersistent, empty.toPersistentList())
76+
}
77+
7178
@Test fun addElements() {
7279
var list = persistentListOf<String>()
7380
list = list.add("x")
@@ -194,6 +201,9 @@ class ImmutableListTest {
194201
testNoOperation({ remove('d') }, { remove('d') })
195202
testNoOperation({ removeAll(listOf('d', 'e')) }, { removeAll(listOf('d', 'e')) })
196203
testNoOperation({ removeAll { it.isUpperCase() } }, { removeAll { it.isUpperCase() } })
204+
testNoOperation({ removeAll(emptyList()) }, { removeAll(emptyList())})
205+
testNoOperation({ addAll(emptyList()) }, { addAll(emptyList())})
206+
testNoOperation({ addAll(2, emptyList()) }, { addAll(2, emptyList())})
197207
}
198208
}
199209

core/commonTest/src/contract/map/ImmutableMapTest.kt

+6
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,12 @@ abstract class ImmutableMapTest {
191191
assertEquals<Map<*, *>>(map, immMap) // problem
192192
}
193193

194+
@Test fun emptyMapToPersistentMap() {
195+
val empty = emptyMap<String, Int>()
196+
val emptyPersistentMap = empty.toPersistentMap()
197+
198+
assertSame(emptyPersistentMap, empty.toPersistentMap())
199+
}
194200

195201
@Test fun putElements() {
196202
var map = immutableMapOf<String, Int?>().toPersistentMap()

core/commonTest/src/contract/set/ImmutableSetTest.kt

+9
Original file line numberDiff line numberDiff line change
@@ -339,13 +339,22 @@ abstract class ImmutableSetTestBase {
339339
val set = immutableSetOf("abcxyz12".toList())
340340
with(set) {
341341
testNoOperation({ add('a') }, { add('a') })
342+
testNoOperation({ addAll(emptySet()) }, { addAll(emptySet()) })
342343
testNoOperation({ addAll(listOf('a', 'b')) }, { addAll(listOf('a', 'b')) })
343344
testNoOperation({ remove('d') }, { remove('d') })
344345
testNoOperation({ removeAll(listOf('d', 'e')) }, { removeAll(listOf('d', 'e')) })
345346
testNoOperation({ removeAll { it.isUpperCase() } }, { removeAll { it.isUpperCase() } })
347+
testNoOperation({ removeAll(emptySet()) }, { removeAll(emptySet()) })
346348
}
347349
}
348350

351+
@Test fun emptySetToPersistentSet() {
352+
val empty = emptySet<Int>()
353+
val emptyPersistentSet = empty.toPersistentSet()
354+
355+
assertSame(emptyPersistentSet, empty.toPersistentSet())
356+
}
357+
349358
fun <T> PersistentSet<T>.testNoOperation(persistent: PersistentSet<T>.() -> PersistentSet<T>, mutating: MutableSet<T>.() -> Unit) {
350359
val result = this.persistent()
351360
val buildResult = this.mutate(mutating)

0 commit comments

Comments
 (0)