diff options
-rw-r--r-- | src/library/scala/collection/TraversableLike.scala | 18 | ||||
-rw-r--r-- | src/library/scala/collection/mutable/Builder.scala | 20 |
2 files changed, 33 insertions, 5 deletions
diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala index 0345f05355..b2051bf209 100644 --- a/src/library/scala/collection/TraversableLike.scala +++ b/src/library/scala/collection/TraversableLike.scala @@ -235,14 +235,19 @@ trait TraversableLike[+A, +Repr] extends Any (that ++ seq)(breakOut) def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = { - val b = bf(repr) - b.sizeHint(this) + def builder = { // extracted to keep method size under 35 bytes, so that it can be JIT-inlined + val b = bf(repr) + b.sizeHint(this) + b + } + val b = builder for (x <- this) b += f(x) b.result } def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = { - val b = bf(repr) + def builder = bf(repr) // extracted to keep method size under 35 bytes, so that it can be JIT-inlined + val b = builder for (x <- this) b ++= f(x).seq b.result } @@ -266,7 +271,12 @@ trait TraversableLike[+A, +Repr] extends Any * @return a new $coll consisting of all elements of this $coll that do not satisfy the given * predicate `p`. The order of the elements is preserved. */ - def filterNot(p: A => Boolean): Repr = filter(!p(_)) + def filterNot(p: A => Boolean): Repr = { + val b = newBuilder + for (x <- this) + if (!p(x)) b += x + b.result + } def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[Repr, B, That]): That = { val b = bf(repr) diff --git a/src/library/scala/collection/mutable/Builder.scala b/src/library/scala/collection/mutable/Builder.scala index bbf4f5889d..b6887df61e 100644 --- a/src/library/scala/collection/mutable/Builder.scala +++ b/src/library/scala/collection/mutable/Builder.scala @@ -62,9 +62,27 @@ trait Builder[-Elem, +To] extends Growable[Elem] { * wrong, i.e. a different number of elements is added. * * @param coll the collection which serves as a hint for the result's size. + */ + def sizeHint(coll: TraversableLike[_, _]) { + if (coll.isInstanceOf[collection.IndexedSeqLike[_,_]]) { + sizeHint(coll.size) + } + } + + /** Gives a hint that one expects the `result` of this builder + * to have the same size as the given collection, plus some delta. This will + * provide a hint only if the collection is known to have a cheap + * `size` method. Currently this is assumed to be the case if and only if + * the collection is of type `IndexedSeqLike`. + * Some builder classes + * will optimize their representation based on the hint. However, + * builder implementations are still required to work correctly even if the hint is + * wrong, i.e. a different number of elements is added. + * + * @param coll the collection which serves as a hint for the result's size. * @param delta a correction to add to the `coll.size` to produce the size hint. */ - def sizeHint(coll: TraversableLike[_, _], delta: Int = 0) { + def sizeHint(coll: TraversableLike[_, _], delta: Int) { if (coll.isInstanceOf[collection.IndexedSeqLike[_,_]]) { sizeHint(coll.size + delta) } |