Skip to content

Commit 7ba38a0

Browse files
committed
Merge pull request scala#4202 from kanielc/SI-9043
SI-9043 ArrayBuffer.insert and insertAll are very slow
2 parents 371a28b + 6e8c60e commit 7ba38a0

File tree

2 files changed

+43
-6
lines changed

2 files changed

+43
-6
lines changed

src/library/scala/collection/mutable/ArrayBuffer.scala

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ class ArrayBuffer[A](override protected val initialSize: Int)
128128
override def ++=:(xs: TraversableOnce[A]): this.type = { insertAll(0, xs.toTraversable); this }
129129

130130
/** Inserts new elements at the index `n`. Opposed to method
131-
* `update`, this method will not replace an element with a
131+
* `update`, this method will not replace an element with a new
132132
* one. Instead, it will insert a new element at index `n`.
133133
*
134134
* @param n the index where a new element will be inserted.
@@ -137,12 +137,13 @@ class ArrayBuffer[A](override protected val initialSize: Int)
137137
*/
138138
def insertAll(n: Int, seq: Traversable[A]) {
139139
if (n < 0 || n > size0) throw new IndexOutOfBoundsException(n.toString)
140-
val xs = seq.toList
141-
val len = xs.length
142-
ensureSize(size0 + len)
140+
val len = seq.size
141+
val newSize = size0 + len
142+
ensureSize(newSize)
143+
143144
copy(n, n + len, size0 - n)
144-
xs.copyToArray(array.asInstanceOf[scala.Array[Any]], n)
145-
size0 += len
145+
seq.copyToArray(array.asInstanceOf[Array[Any]], n)
146+
size0 = newSize
146147
}
147148

148149
/** Removes the element on a given index position. It takes time linear in
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package scala.collection.mutable
2+
3+
import org.junit.runner.RunWith
4+
import org.junit.runners.JUnit4
5+
import org.junit.{Assert, Test}
6+
7+
import scala.tools.testing.AssertUtil
8+
9+
/* Test for SI-9043 */
10+
@RunWith(classOf[JUnit4])
11+
class ArrayBufferTest {
12+
@Test
13+
def testInsertAll: Unit = {
14+
val traver = ArrayBuffer(2, 4, 5, 7)
15+
val testSeq = List(1, 3, 6, 9)
16+
17+
def insertAt(x: Int) = {
18+
val clone = traver.clone()
19+
clone.insertAll(x, testSeq)
20+
clone
21+
}
22+
23+
// Just insert some at position 0
24+
Assert.assertEquals(ArrayBuffer(1, 3, 6, 9, 2, 4, 5, 7), insertAt(0))
25+
26+
// Insert in the middle
27+
Assert.assertEquals(ArrayBuffer(2, 4, 1, 3, 6, 9, 5, 7), insertAt(2))
28+
29+
// No strange last position weirdness
30+
Assert.assertEquals(ArrayBuffer(2, 4, 5, 7, 1, 3, 6, 9), insertAt(traver.size))
31+
32+
// Overflow is caught
33+
AssertUtil.assertThrows[IndexOutOfBoundsException] { insertAt(-1) }
34+
AssertUtil.assertThrows[IndexOutOfBoundsException] { insertAt(traver.size + 10) }
35+
}
36+
}

0 commit comments

Comments
 (0)