第83讲:Scala中List的实现内幕源码揭秘学习笔记
来源:互联网 发布:qq加人软件 编辑:程序博客网 时间:2024/06/07 06:30
第83讲:Scala中List的实现内幕源码揭秘学习笔记
本讲主要讲解List实现的具体内部的关键源码
上讲讲了listbuffer对list的高效遍历,解决了堆栈溢出的问题和使用遍历时的效率问题
scala中的list在后来的版本中都采用了这种方法。
toList不会低效,ListBuffer最后 一个元素是List的最后一个元素,
/*Converts this buffer to a list.Takes constant time. The buffer is
copied lazily, the first time it is mutated.*/
override def toList: List[A] = {
exported = !start.isEmppty
start //只是返回start,基本不耗时间。start指向元素列表
}
//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是一个高效的方法。
toList不会复制存储在ListBuffer中的列表,只是返回,所以效率很高。
final case class ::[B](private var hd: B,private[scala] var tl: List[B] extends List[B]){
//默认情况下List都是不可变元素。
//private[scala] var tl可以看出,外部不可修改tl,只有在scala包中才能修改。
//往列表中增加元素时内部都是利用ListBuffer方式去做的。
override def head : B = hd
override def tail : List[B] = tl
override def isEmpty: Bollean = false
private def readObject(in: ObjectInputStream){
val firstObject = in.readObject()
hd = firstObject.asInstanceOf[B]
assert(hd != ListSerializeEnd)
var current: ::[B] = this
while (true) in.readObject match {
case ListSerializeEnd =>
current.tl = Nil
return
case a =>
val list : ::[B] = new ::(a.asInstanceOf[B],Nil)
current.tl = list
current = this
}
}
private def writeObject(out: ObjectOutputStream){
var xs:List[B] = this
while (!xs.isEmpty) { out.writeObject(xs.head);xs = xs.tail}
out.writeObject(ListSerializeEnd)
}
}
往List中追加元素:
def += (x: A): this.type = {
if (exported) copy() //对不变列表操作时,会产生一个新列表
if (start.isEmpty) {
last0 = new :: (x, Nil)
start = last0
} else {
val last1 = last0
last0 = new :: (x, Nil)
last1.t1 = last0
//不断在后面追加元素。
}
len += 1
this
private def copy(){
var cursor = start
val limit = last0.tail
clear()
while (cursor ne limit){
this += cursor.head
cursor = cursor.tail
}
}
//可以看出copy是比较花时间的。
}
exported为ListBuffer中的flag(default:false),
当flag为true时,表明Buffer已进行了toList操作,
此时再进行连接等操作时,会有copy链表的动作发生,
消耗内存,在实际编程中应谨慎。
toList之后就尽量不要再修改元素。
- 第83讲:Scala中List的实现内幕源码揭秘学习笔记
- Scala深入浅出进阶经典 第83讲:Scala中List的实现内幕源码揭秘
- 【DT大数据梦工厂视频】《第83讲:Scala中List的实现内幕源码揭秘》
- 第83讲:Scala中List的实现内幕源码揭秘
- Scala深入浅出进阶经典 第41讲:List继承体系实现内幕和方法操作源码揭秘
- 第89讲:Scala中使用For表达式实现内幕思考学习笔记
- 第82讲:Scala中List的ListBuffer是如何实现高效的遍历计算的?学习笔记
- 第84讲:Scala中List和ListBuffer设计实现思考学习笔记
- 第62讲:Scala中上下文界定内幕中的隐式参数与隐式参数的实战详解及其在Spark中的应用源码解析学习笔记
- scala-41:List继承体系实现内幕和方法操作源码揭秘
- 第81讲:Scala中List的构造时的类型约束逆变、协变、下界详解学习笔记
- Scala深入浅出进阶经典 第89讲:Scala中使用For表达式实现内幕思考
- scala-31:Option使用和实现内幕源码揭秘
- 第82讲:Scala中List的ListBuffer是如何实现高效的遍历计算的?
- 第82讲:Scala中List的ListBuffer实现高效的遍历计算
- Scala深入浅出进阶经典 第65讲:Scala中隐式转换内幕操作规则揭秘、最佳实践及其在Spark中的应用源码解析
- Scala深入浅出进阶经典 第82讲:Scala中List的ListBuffer是如何实现高效的遍历计算的
- 第74讲:从Spark源码的角度思考Scala中的模式匹配学习笔记
- 学习英语经验
- Linux常用命令002之搜索命令locate、whereis、which、find、grep
- ubuntu 10.04更新源
- OC中字典的使用,数组的使用----省市区
- 文本处理类命令
- 第83讲:Scala中List的实现内幕源码揭秘学习笔记
- AspNetPager在有些网页的地方显示的是换行的
- 安全删除STL容器元素
- C++之运算符重载
- Java三目运算
- 360机试题:挑选镇长
- MFC按键控制
- Perl 监控Redis
- [Leetcode]Count and Say