scala.collection.mutable.Builder.scala Maven / Gradle / Ivy
/*
* Scala (https://www.scala-lang.org)
*
* Copyright EPFL and Lightbend, Inc.
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/
package scala
package collection
package mutable
import generic._
/** The base trait of all builders.
* A builder lets one construct a collection incrementally, by adding
* elements to the builder with `+=` and then converting to the required
* collection type with `result`.
*
* One cannot assume that a single `Builder` can build more than one
* instance of the desired collection. Particular subclasses may allow
* such behavior. Otherwise, `result` should be treated as a terminal
* operation: after it is called, no further methods should be called on
* the builder. Extend the [[collection.mutable.ReusableBuilder]] trait
* instead of `Builder` for builders that may be reused to build multiple
* instances.
*
* @tparam Elem the type of elements that get added to the builder.
* @tparam To the type of collection that it produced.
*
* @since 2.8
*/
trait Builder[-Elem, +To] extends Growable[Elem] {
/** Adds a single element to the builder.
* @param elem the element to be added.
* @return the builder itself.
*/
def +=(elem: Elem): this.type
/** Clears the contents of this builder.
* After execution of this method the builder will contain no elements.
*/
def clear()
/** Produces a collection from the added elements. This is a terminal operation:
* the builder's contents are undefined after this operation, and no further
* methods should be called.
*
* @return a collection containing the elements added to this builder.
*/
def result(): To
/** Gives a hint how many elements are expected to be added
* when the next `result` is called. 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 size the hint how many elements will be added.
*/
def sizeHint(size: Int) {}
/** 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, which is determined by calling `sizeHint`.
*
* 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.
*/
def sizeHint(coll: TraversableLike[_, _]) {
coll.sizeHintIfCheap match {
case -1 =>
case n => sizeHint(n)
}
}
/** 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) {
coll.sizeHintIfCheap match {
case -1 =>
case n => sizeHint(n + delta)
}
}
/** Gives a hint how many elements are expected to be added
* when the next `result` is called, together with an upper bound
* given by the size of some other collection. 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 size the hint how many elements will be added.
* @param boundingColl the bounding collection. If it is
* an IndexedSeqLike, then sizes larger
* than collection's size are reduced.
*/
def sizeHintBounded(size: Int, boundingColl: TraversableLike[_, _]) {
boundingColl.sizeHintIfCheap match {
case -1 =>
case n => sizeHint(size min n)
}
}
/** Creates a new builder by applying a transformation function to
* the results of this builder.
* @param f the transformation function.
* @tparam NewTo the type of collection returned by `f`.
* @return a new builder which is the same as the current builder except
* that a transformation function is applied to this builder's result.
*
* @note The original builder should no longer be used after `mapResult` is called.
*/
def mapResult[NewTo](f: To => NewTo): Builder[Elem, NewTo] =
new Builder[Elem, NewTo] with Proxy {
val self = Builder.this
def +=(x: Elem): this.type = { self += x; this }
def clear() = self.clear()
override def ++=(xs: TraversableOnce[Elem]): this.type = { self ++= xs; this }
override def sizeHint(size: Int) = self.sizeHint(size)
override def sizeHintBounded(size: Int, boundColl: TraversableLike[_, _]) = self.sizeHintBounded(size, boundColl)
def result: NewTo = f(self.result())
}
}