Scala的List主要属性为head和tail。
def head: A
def tail: List[A]
其中head为List的头部成员,而tail则为除了队首之外的元素的List对象。
Scala中的List可以通过类似::的操作来连接个元素组成一个List。
def ::[B >: A] (x: B): List[B] =
new scala.collection.immutable.::(x, this)
其中新加入的队首元素必须其类型必须是当前List中所包含元素的类型的超类,该List所保存的元素类型也会被视为新的类型,之后构造新的case类 ::。
final case class ::[B](override val head: B, private[scala] var tl: List[B]) extends List[B] {
override def tail : List[B] = tl
override def isEmpty: Boolean = false
}
::约定该List的队首和tail为当前原有List,并保证为非空。
:::则可以完成List与List之前的连接。
def :::[B >: A](prefix: List[B]): List[B] =
if (isEmpty) prefix
else if (prefix.isEmpty) this
else (new ListBuffer[B] ++= prefix).prependToList(this)
如果当前List为空,则直接返回前置List,如果前置List为空,则直接返回当前List。
如果两者均不为空,则会通过ListBuffer的++=方法首先复制前置List。++=的主要逻辑主要在Growable中。
def ++=(xs: TraversableOnce[A]): this.type = {
@tailrec def loop(xs: scala.collection.LinearSeq[A]) {
if (xs.nonEmpty) {
this += xs.head
loop(xs.tail)
}
}
xs match {
case xs: scala.collection.LinearSeq[_] => loop(xs)
case xs => xs foreach +=
}
this
}
如果参数为LinearSeq类(List继承自该类),将会在已经定义好的loop()方法中之心,否则需要自定义+=方法。
在loop()中将会依次将head取出保存,在得到tail在下一次递归继续去head元素。
在完成前置List的复制后,将会通过pretendToList()加上当前List并转为List。
def prependToList(xs: List[A]): List[A] = {
if (isEmpty) xs
else {
if (exported) copy()
last0.tl = xs
toList
}
map()方法将对List中的元素重新进行计算。
final override def map[B, That](f: A => B)(implicit bf: CanBuildFrom[List[A], B, That]): That = {
if (bf eq List.ReusableCBF) {
if (this eq Nil) Nil.asInstanceOf[That] else {
val h = new ::[B](f(head), Nil)
var t: ::[B] = h
var rest = tail
while (rest ne Nil) {
val nx = new ::(f(rest.head), Nil)
t.tl = nx
t = nx
rest = rest.tail
}
h.asInstanceOf[That]
}
}
else super.map(f)
}
在之定义新的转换函数,而采用默认的隐式函数的情况下,将会依次对List中的元素进行转换。
首先会对head元素进行转换,并生成新的case类::,之后会不断依次从tail往下遍历,不断根据下一个元素生成一个队首元素为下一个元素的新List作为tail并接下来以新的List的tail来接受下一个元素生成的新List。
其余遍历操作核心都类似map()操作。