Scala的Seq实现的初步分析

对于Scala Seq集合

有常见操作:

val platformTypes = Seq("ANDROID", "IOS", "WEB")

该Seq类型在顶级包scala中被定义:

type Seq[+A] = scala.collection.Seq[A]
val Seq = scala.collection.Seq

查看Seq源码,实际Seq本身的定义是非常简单的,且Scala的所有集合基本都是一个类似的使用模板的实现结构

trait Seq[+A] extends PartialFunction[Int, A] //支持偏函数
                      with Iterable[A]//支持迭代器
                      with GenSeq[A]//可并行操作的所有序列的共同特质
                      with GenericTraversableTemplate[A, Seq]//常规集合类的伴随对象的模板特质,代表一种无约束的更高等级的类型
                      with SeqLike[A, Seq[A]] {//Seq[A]的模板特质,Seq主要操作的实现
   
   //构建该类的实例的工厂伴生对象
   //指定伴生对象,实际Seq()是调用的GenericCompanion的apply()方法
  override def companion: GenericCompanion[Seq] = Seq

  //类型
  override def seq: Seq[A] = this
}

/** 
 *  类似工厂方法,Coll的当前默认实现是List
 *  @define coll sequence
 *  @define Coll `Seq`
 */
object Seq extends SeqFactory[Seq] {//SeqFactory是Seq及其子类的伴生对象模板,仅有unapplySeq方法在模式匹配{case Seq(…)=>}中调用
  /**GenTraversableFactory是Traversable及其子类的伴随对象的模板。此类提供了一组用于创建$Coll对象的操作。它通常由Traversable子类的伴随对象继承。当然这里是间接的*/
  //每个集合的伴生对象都定义了隐式方法canBuildFrom
  implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Seq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
  //Seq的构造器,默认使用的是不可变的Seq(使用构造器生成一个Seq)
  def newBuilder[A]: Builder[A, Seq[A]] = immutable.Seq.newBuilder[A]//然而最底层实现其实是一个可变的ListBuffer(继承了Builder特质)
}

/** Explicit instantiation of the `Seq` trait to reduce class file size in subclasses. */
abstract class AbstractSeq[+A] extends AbstractIterable[A] with Seq[A]

canBuildFrom在转化集合时(如 toList)会自动引入(因为在伴生对象域内的隐式方法都会自动对本类型的实例可见)
最终调用CanBuildFrom的apply()方法构造一个对应的builder(该builder就是上面ReusableCBF返回的子类的newBuilder方法实现,也就是immutable.Seq.newBuilder[A])

def to[Col[_]](implicit cbf: CanBuildFrom[Nothing, A, Col[A @uV]]): Col[A @uV] = {
  val b = cbf()
  b ++= seq
  b.result()
}

newBuilder不仅在集合转化中实现,使用伴生对象创建Seq实例时newBuilder方法也会被调用。在调用本Seq的伴生对象时会调用GenericCompanion的apply来使用

abstract class GenericCompanion[+CC[X] <: GenTraversable[X]] {
  /** The underlying collection type with unknown element type */
  protected[this] type Coll = CC[_]

  def newBuilder[A]: Builder[A, CC[A]]

  def empty[A]: CC[A] = newBuilder[A].result()

  //使用Seq中的定义def newBuilder[A]: Builder[A, Seq[A]] = immutable.Seq.newBuilder[A]实现来生成Seq对象实例
  def apply[A](elems: A*): CC[A] = {
    if (elems.isEmpty) empty[A]
    else {
      val b = newBuilder[A]
      //使用builder存储元素,并返回结果
      b ++= elems
      b.result()
    }
  }
}

几乎所有集合的具体实现都在*Like中实现。这是一种作为通用模板的特质,Seq集合对应的是SeqLike。
其中SeqLike的方法indexOfSlice、lastIndexOfSlice、indexOf等都使用了kmp算法查找。

鉴于好多人还在CSDN,再冒个泡。原文 https://dreamylost.cn/。不定时搬运自己的博客到这里来

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值