scala List源码

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()操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值