初学者,浅浅的读下源码,如有不对的地方烦请指教。
map方法
拿出几何或者列表中的每个元素进行处理。
案例一:map对单词进行分割
object WordCount {
def main(args: Array[String]): Unit = {
val stringList = List("hello Scala Hbase kafka", "Hello Scala Hbase", "Hello Scala", "Hello")
//1 对单词进行分割
val wordList = stringList.map(_.split(" "))
println(wordList.flatten))
}
}
map源码
final override def map[B](f: A => B): List[B] = {
//this为stringList,如果里面没有元素就返回Nil
if (this eq Nil) Nil else {
//先执行f(head), 也就是split(head),将头元素进行分割new一个新List:h放入分割后的元素
//注意:个人理解,双冒号::其实就是连接列表list,也可以用作new一个新列表,相当于Nil :: f(head)
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.next = nx
t = nx
rest = rest.tail
}
releaseFence()
h
}
}
一句一句分析
if (this eq Nil) Nil
this为stringList,如果里面没有元素就返回Nil。否则,列表头元素按空格分割放在h中
val h = new ::[B](f(head), Nil)
先执行f(head), 也就是split(head),将头元素进行分割new一个新List:h放入分割后的元素,返回结果如下图
注意:个人理解,双冒号::其实就是连接列表list,也可以用作new一个新列表,相当于Nil :: f(head)
var t: ::[B] = h
这是一个临时变量t,指向h,为了遍历增加链表节点。
var rest = tail
rest为列表除了列表头以外的尾部元素,如下图:
while (rest ne Nil) {
val nx = new ::(f(rest.head), Nil)
t.next = nx
t = nx
rest = rest.tail
}
接下来就是循环遍历列表的元素,nx为列表除了头以外的元素做split处理后的得到的单词列表,接下来就是不停的将nx连接在上一个节点后面,t再指向后面一个节点,直到遍历分割完列表元素。
大概的图示就是下面这个图:
releaseFence()
h
最后返回的就是h,返回结果是链表存放的数组地址,类型就是List[Array[String]]:
List([Ljava.lang.String;@5f2050f6, [Ljava.lang.String;@3b81a1bc, [Ljava.lang.String;@64616ca2, [Ljava.lang.String;@13fee20c)
最后进行flatten展开操作返回一个单词列表
List(hello, Scala, Hbase, kafka, Hello, Scala, Hbase, Hello, Scala, Hello)
看到后面才发现,类似于一个链表,里面存放的是String类型的数组:Array[String]如下图: