Skip to content

Commit e117a39

Browse files
authored
Merge pull request scala/scala#8260 from retronym/backport/listbuffer-performance
Backport ListBuffer.+= optimizations
2 parents 034e782 + 1b18ee5 commit e117a39

File tree

1 file changed

+16
-18
lines changed

1 file changed

+16
-18
lines changed

library/src/scala/collection/mutable/ListBuffer.scala

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ final class ListBuffer[A]
6666
*/
6767
private var start: List[A] = Nil
6868
private var last0: ::[A] = _
69-
private var exported: Boolean = false
70-
private var len = 0
69+
private[this] var exported: Boolean = false
70+
private[this] var len = 0
7171

7272
protected def underlying: List[A] = start
7373

@@ -143,7 +143,7 @@ final class ListBuffer[A]
143143
def update(n: Int, x: A) {
144144
// We check the bounds early, so that we don't trigger copying.
145145
if (n < 0 || n >= len) throw new IndexOutOfBoundsException(n.toString)
146-
if (exported) copy()
146+
ensureUnaliased()
147147
if (n == 0) {
148148
val newElem = new :: (x, start.tail)
149149
if (last0 eq start) {
@@ -171,15 +171,10 @@ final class ListBuffer[A]
171171
* @return this $coll.
172172
*/
173173
def += (x: A): this.type = {
174-
if (exported) copy()
175-
if (isEmpty) {
176-
last0 = new :: (x, Nil)
177-
start = last0
178-
} else {
179-
val last1 = last0
180-
last0 = new :: (x, Nil)
181-
last1.tl = last0
182-
}
174+
ensureUnaliased()
175+
val last1 = new ::[A](x, Nil)
176+
if (len == 0) start = last1 else last0.tl = last1
177+
last0 = last1
183178
len += 1
184179
this
185180
}
@@ -209,7 +204,7 @@ final class ListBuffer[A]
209204
* @return this $coll.
210205
*/
211206
def +=: (x: A): this.type = {
212-
if (exported) copy()
207+
ensureUnaliased()
213208
val newElem = new :: (x, start)
214209
if (isEmpty) last0 = newElem
215210
start = newElem
@@ -228,7 +223,7 @@ final class ListBuffer[A]
228223
def insertAll(n: Int, seq: Traversable[A]) {
229224
// We check the bounds early, so that we don't trigger copying.
230225
if (n < 0 || n > len) throw new IndexOutOfBoundsException(n.toString)
231-
if (exported) copy()
226+
ensureUnaliased()
232227
var elems = seq.toList.reverse
233228
len += elems.length
234229
if (n == 0) {
@@ -276,7 +271,7 @@ final class ListBuffer[A]
276271
if (count < 0) throw new IllegalArgumentException("removing negative number of elements: " + count.toString)
277272
else if (count == 0) return // Nothing to do
278273
if (n < 0 || n > len - count) throw new IndexOutOfBoundsException("at " + n.toString + " deleting " + count.toString)
279-
if (exported) copy()
274+
ensureUnaliased()
280275
val n1 = n max 0
281276
val count1 = count min (len - n1)
282277
if (n1 == 0) {
@@ -327,7 +322,7 @@ final class ListBuffer[A]
327322
def prependToList(xs: List[A]): List[A] = {
328323
if (isEmpty) xs
329324
else {
330-
if (exported) copy()
325+
ensureUnaliased()
331326
last0.tl = xs
332327
toList
333328
}
@@ -345,7 +340,7 @@ final class ListBuffer[A]
345340
*/
346341
def remove(n: Int): A = {
347342
if (n < 0 || n >= len) throw new IndexOutOfBoundsException(n.toString())
348-
if (exported) copy()
343+
ensureUnaliased()
349344
var old = start.head
350345
if (n == 0) {
351346
start = start.tail
@@ -371,7 +366,7 @@ final class ListBuffer[A]
371366
* @return this $coll.
372367
*/
373368
override def -= (elem: A): this.type = {
374-
if (exported) copy()
369+
ensureUnaliased()
375370
if (isEmpty) {}
376371
else if (start.head == elem) {
377372
start = start.tail
@@ -439,6 +434,9 @@ final class ListBuffer[A]
439434
}
440435

441436
// Private methods
437+
private def ensureUnaliased() = {
438+
if (exported) copy()
439+
}
442440

443441
/** Copy contents of this buffer */
444442
private def copy() {

0 commit comments

Comments
 (0)