scala Builder 由来方法源码分析
由来
scala.collection.mutable.Builder
是 Scala 集合框架中的一个 trait,用于定义可变集合构建器的基本特质。构建器允许我们通过添加元素来构建集合,并最终将其转换为所需的集合类型。
该特质的设计目的是为了提供一种通用的方式来构建可变集合,不依赖于具体的集合实现。因此,它被设计为具有泛型参数 Elem
和 To
,分别表示要添加到构建器的元素类型和生成的集合类型。
Builder
特质继承自 Growable
特质,Growable
定义了向集合添加元素的方法。这意味着所有实现了 Builder
特质的类都必须提供 +=
方法来添加元素。
方法
除了 +=
方法之外,Builder
还定义了其他几个重要的方法:
clear()
:清空构建器的内容。result()
:将已添加的元素转换为目标集合类型并返回。sizeHint(size: Int)
:给出预期添加元素数量的提示,用于优化构建器的性能。sizeHint(coll: TraversableLike[_, _])
和sizeHint(coll: TraversableLike[_, _], delta: Int)
:根据已知集合的大小给出结果集合的大小提示。
通过实现 Builder
特质,我们可以创建自定义的构建器,以构建各种可变集合。这样可以在添加元素时灵活地控制集合的构建过程,并最终生成所需的集合类型。
总结起来,Builder
特质是 Scala 集合框架中用于构建可变集合的基本特质,提供了添加元素、清空构建器、转换结果集合等功能。它为我们提供了一种通用的方式来构建可变集合,使得集合的构建过程更加灵活和可控。
中文源码
/** 所有构建器的基本特质。
* 构建器允许通过使用 `+=` 方法向构建器添加元素,并使用 `result` 方法将其转换为所需的集合类型。
*
* @tparam Elem 要添加到构建器的元素类型。
* @tparam To 生成的集合类型。
*
* @since 2.8
*/
trait Builder[-Elem, +To] extends Growable[Elem] {
/** 向构建器添加单个元素。
* @param elem 要添加的元素。
* @return 构建器本身。
*/
def +=(elem: Elem): this.type
/** 清空构建器的内容。
* 执行此方法后,构建器将不包含任何元素。
*/
def clear()
/** 从已添加的元素中生成一个集合。
* 此操作后,构建器的内容将未定义。
* @return 包含添加到此构建器的元素的集合。
*/
def result(): To
/** 给出预期添加元素数量的提示。
* 某些构建器类可以根据提示对其表示进行优化。
* 不过,即使提示错误(即添加了不同数量的元素),构建器实现仍然需要正确工作。
*
* @param size 预期添加的元素数量的提示。
*/
def sizeHint(size: Int) {}
/** 给出一个提示,预期此构建器的 `result` 的大小与给定集合相同,加上一些增量。
* 只有当已知集合具有廉价的 `size` 方法时,此方法提供提示。
* 目前,只有类型为 `IndexedSeqLike` 的集合被认为具有廉价的 `size` 方法。
* 某些构建器类可以根据提示对其表示进行优化。
* 不过,即使提示错误(即添加了不同数量的元素),构建器实现仍然需要正确工作。
*
* @param coll 用于结果大小提示的集合。
*/
def sizeHint(coll: TraversableLike[_, _]) {
if (coll.isInstanceOf[collection.IndexedSeqLike[_,_]]) {
sizeHint(coll.size)
}
}
/** 给出一个提示,预期此构建器的 `result` 的大小与给定集合相同,加上一些增量。
* 只有当已知集合具有廉价的 `size` 方法时,此方法提供提示。
* 目前,只有类型为 `IndexedSeqLike` 的集合被认为具有廉价的 `size` 方法。
* 某些构建器类可以根据提示对其表示进行优化。
* 不过,即使提示错误(即添加了不同数量的元素),构建器实现仍然需要正确工作。
*
* @param coll 用于结果大小提示的集合。
* @param delta 要添加到 `coll.size` 的修正值,以得到大小提示。
*/
def sizeHint(coll: TraversableLike[_, _], delta: Int) {
if (coll.isInstanceOf[collection.IndexedSeqLike[_,_]]) {
sizeHint(coll.size + delta)
}
}
/** 给出预期添加元素数量的提示,并提供一个上限,由另一个集合的大小给出。
* 某些构建器类可以根据提示对其表示进行优化。
* 不过,即使提示错误(即添加了不同数量的元素),构建器实现仍然需要正确工作。
*
* @param size 预期添加的元素数量的提示。
* @param boundingColl 边界集合。如果它是 IndexedSeqLike,则减小大于集合大小的大小提示。
*/
def sizeHintBounded(size: Int, boundingColl: TraversableLike[_, _]) {
if (boundingColl.isInstanceOf[collection.IndexedSeqLike[_,_]])
sizeHint(size min boundingColl.size)
}
/** 通过将转换函数应用于此构建器的结果来创建一个新的构建器。
* @param f 转换函数。
* @tparam NewTo `f` 返回的集合类型。
* @return 一个新的构建器,与当前构建器相同,只是对该构建器的结果应用了转换函数。
*/
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())
}
}
这个方法是在构建器的基础上应用一个转换函数,生成一个新的构建器。新的构建器的元素类型为Elem
,结果集合类型为NewTo
。
具体实现中,通过创建一个匿名类继承自Builder[Elem, NewTo]
和Proxy
特质来定义新的构建器。其中self
引用了原始构建器,用于委托原始构建器的方法调用。
新的构建器重载了+=
方法,将元素添加到原始构建器中,并返回自身。clear
方法清空原始构建器的内容。++=
方法将另一个可遍历对象中的元素追加到原始构建器中,并返回自身。
此外,还重载了sizeHint
、sizeHintBounded
方法,直接委托给原始构建器。
最后,result
方法应用转换函数f
到原始构建器的结果上,并返回转换后的结果。