1. 程式人生 > >第83講:Scala中List的實現內幕原始碼揭祕

第83講:Scala中List的實現內幕原始碼揭祕

本講視訊是王家林老師通過認真解讀scala原始碼的方式講解了《Scala中List的實現內幕原始碼揭祕》。本講內容如下: ListBuffer(連結串列快取)相當於List的一個工具類,List本身繼承ListBuffer,擁有ListBuffer中非私有的方法。對List的操作其實有部分是通過ListBuffer完成的。exported為LiftBuffer中flag(default:false),當flag為true時,表明Buffer已進行了toList操作,此時再進行連線等操作時,會有copy連結串列的動作發生,消耗記憶體,在實際程式設計中應謹慎。 scala的Listd take(n:Int)原始碼: override def take(n:Int):List[A]={ val b = new ListBuffer[A] var i= 0 var these = this while(!these.isEmpty && i<n){ i += 1 b += these.tail } if(these.isEmpty) this else b.toList } 這裡構建了一個高效的ListBuffer的例項b,最後將例項b通過b.toList方法變成List.toList方法的原始碼如下: override def toList:List[A]={ exported = !start.isEmpty start } 這裡ListBuffer返回的是其第一個元素,所以ListBuffer的toList是一個高效的方法。 List的子類::的原始碼如下: final case class ::[B](private var hd:B,private[scala] var tl:List[B])extends List[B]{....} 這裡第二個引數tl是除了第一個引數之外所構成的一個List,修飾符private[scala]表示只有scala包下的物件才能訪問,所以ListBuffer可以訪問第二個引數tl。 ListBuffer的原始碼如下: private var start:List[A] = Nil private var last0: ::[A]=_ private exported:Boolean = false private var len = 0 這裡的start指向了儲存快取的所有列表,預設值是Nil. ListBuffer的toList方法的原始碼如下: override def toList:List[A]={ exported = !start.isEmpty start } 所以toList不會複製儲存ListBuffer裡面的列表,他只負責返回第一個元素,所以toList的效率非常高。 ListBuffer的追加元素的方法+=的原始碼如下: def +=(x:A): this.type = { if(exported)copy() ..... } 這說明如果ListBuffer變成了List的時候我們就把它複製一份,這就產生了一個新的列表。