From b791ca1ff503233794e87b759e5c23779ff86f12 Mon Sep 17 00:00:00 2001 From: Chua Chee Seng Date: Mon, 20 Jul 2026 21:42:49 +0800 Subject: [PATCH] Use foreach and sizeHint in deleted, updatedWith, splitAround MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All three methods traversed via a manual iterator/while loop even though none of them need iterator-specific capabilities (resumable position, early termination) — every element is visited regardless. Switch them to foreach, which dispatches to each collection's native traversal (e.g. List walking cons cells, index-based loops for array-backed types) instead of paying for an Iterator allocation plus two virtual calls (hasNext/next) per element. - deleted: also add b.sizeHint(this, -1), since the result size is always known exactly (one fewer than the source) when a valid index is found. - updatedWith: also add b.sizeHint(this), optimistically assuming the common case where f returns Some (same size as source); sizeHint is documented to tolerate being wrong, so a None at the matched index just means a harmless one-off overshoot. Also replace the manual Some/None match with f(a).foreach(b += _), matching the idiom used elsewhere. - splitAround: rewritten as a single boolean-flag state machine (switched) instead of two sequential iterator loops. No sizeHint added here — the split point is data-dependent, so neither builder has a reliable size estimate in advance. No behavior changes. --- library/src/scala/collection/Seq.scala | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/library/src/scala/collection/Seq.scala b/library/src/scala/collection/Seq.scala index 1803c14ca30e..ca4fb27e08ad 100644 --- a/library/src/scala/collection/Seq.scala +++ b/library/src/scala/collection/Seq.scala @@ -986,11 +986,10 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any def deleted(index: Int): C^{this} = { if (index < 0) throw new IndexOutOfBoundsException(index.toString) val b = newSpecificBuilder - val it = iterator + b.sizeHint(this, -1) var i = 0 var found = false - while (it.hasNext) { - val a = it.next() + foreach { a => if (i == index) found = true else b += a i += 1 } @@ -1015,17 +1014,13 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any def updatedWith[B >: A](index: Int, f: A => Option[B]): CC[B]^{this} = { if (index < 0) throw new IndexOutOfBoundsException(index.toString) val b = iterableFactory.newBuilder[B] - val it = iterator + b.sizeHint(this) var i = 0 var found = false - while (it.hasNext) { - val a = it.next() + foreach { a => if (i == index) { found = true - f(a) match { - case Some(replacement) => b += replacement - case None => - } + f(a).foreach(b += _) } else b += a i += 1 } @@ -1049,13 +1044,12 @@ transparent trait SeqOps[+A, +CC[_], +C] extends Any def splitAround[A1 >: A](separator: A1): (C^{this}, C^{this}) = { val before = newSpecificBuilder val after = newSpecificBuilder - val it = iterator - var found = false - while (!found && it.hasNext) { - val a = it.next() - if (a == separator) found = true else before += a + var switched = false + foreach { a => + if (switched) after += a + else if (a == separator) switched = true + else before += a } - while (it.hasNext) after += it.next() (before.result(), after.result()) }