scala 高級編程


一、函數式編程

      Scala中的函數可以獨立存在, 不需要依賴任 何類和對象 

       def  放在類中就是方法;放在外邊就是函數

     1、將函數賦值給變量

           Scala中的函數是一等公民, 可以獨立定義, 獨立存在, 而且可以直接將函數作為  值賦值給變量
           Scala的語法規定, 將函數賦值給變量時, 必須在函數后面加上空格和下划線 
       

def sayHello(name: String) { println("Hello, " + name) }
val sayHelloFunc = sayHello _
sayHelloFunc("leo")

  2、匿名函數

         Scala中, 函數也可以不需要命名, 此時函數被稱為匿名函數。

         可以直接定義函數之后, 將函數賦值給某個變量; 也可以將直接定義的匿名  函數傳入其他函數之中
         Scala定義匿名函數的語法規則:  (參數名: 參數類型) => 函數體
         這種匿名函數的語法必須深刻理解和掌握, 在Spark的中有大量這樣的語法。

           val sayHelloFunc = (name: String) => println("Hello, " + name)

      3、高階函數

           Scala中, 由於函數是一等公民, 因此可以直接將某個函數傳入其他函數, 作為參數。  這個功能是極其強大的, 也是Java這種面向對象的編程語言所不具備的。
           接收其他函數作為參數的函數, 也被稱作高階函數( higher-order function) 
      

val sayHelloFunc = (name: String) => println("Hello, " + name)
def greeting(func: (String) => Unit, name: String) { func(name) }
greeting(sayHelloFunc, "leo")

      例:Array(1, 2, 3, 4, 5).map((num: Int) => num * num)  

         高階函數的另外一個功能是將函數作為返回值

          

def getGreetingFunc(msg: String) = (name: String) => println(msg + ", " + name)
val greetingFunc = getGreetingFunc("hello")
greetingFunc("leo")

  輸出結果:hello ,leo

      4、  高階函數的寫法 :高階函數可以自動推斷出參數類型, 而不需要寫明類型。   而且對於只有一個參數的函數, 還可以省去其小括號
                             

def greeting(func: (String) => Unit, name: String) { func(name) }
greeting((name: String) => println("Hello, " + name), "leo")
greeting((name) => println("Hello, " + name), "leo")
greeting(name => println("Hello, " + name), "leo")

  5、Scala的常用高階函數

          map: 對傳入的每個元素都進行映射, 返回一個處理后的元素

                  Array(1, 2, 3, 4, 5).map(2 * _)       下划線和2可以調換位置

           foreach: 對傳入的每個元素都進行處理, 但是沒有返回值

                    (1 to 9).map("*" * _).foreach(println _)            foreach是對map最后結果之后的操作

           filter: 對傳入的每個元素都進行條件判斷, 如果對元素返回true, 則保留  該元素, 否則過濾掉該元素 

                   (1 to 20).filter(_ % 2 == 0)                  list.filter(x=>x.contains(2))取出包含2的list

       6、reduceLeft: 從左側元素開始, 進行reduce操作, 即先對元素1和元素2  進行處理, 然后將結果與元素3處理, 再將結果與元素4處理, 依次類推,  即為reducereduce操作必須掌握!

spark編程的重點! ! !
           下面這個操作就相當於1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9
            (1 to 9).reduceLeft( _ * _)           相當於(1 to 9).reduce((x,y)=>x*y)
            sortWith: 對元素進行兩兩相比, 進行排序                Array(3, 2, 5, 4, 10, 1).sortWith(_ < _)       相當於Array(3, 2, 5, 4, 10, 1).sortWith((x,y)=>x<y)

二、函數式編程的集合操作
      1、Scala的集合體系結構
           Scala中的集合體系主要包括: IterableSeqSetMap。   其中, Iterable是所有集合trait的根trait, 這個結構與Java的集合體系非常相似。
          Scala中的集合是分成可變和不可變兩類集合的           其中, 可變集合就是說, 集合的元素可以動態修改,  而不可變集合的元素在初始化之后, 就無法修改了。  分別對應scala.collection.mutable

scala.collection.immutable兩個包。 

           Seq下包含了RangeArrayBufferList等子trait。  其中Range就代表了一個序列, 通常可以使用“ 1 to 10” 這種語法來產生一個Range。  ArrayBuffer就類似於Java中的ArrayList
      2、List
            List代表一個不可變的列表, List的創建, val list = List(1, 2, 3, 4)
            Listheadtailhead代表List的第一個元素, tail代表第一個元素之后的所有元素, list.headlist.tail
            List有特殊的::操作符, 可以用於將headtail合並成一個List0 :: list                   三個:是把兩個list合並為一個新的list;和list1::list2是有區別的會生成一個list中的元素各為 一個list
            如果一個List只有一個元素, 那么它的head就是這個元素, 它的tailNil。   Nil是一個空的List, 定義為List[Nothing]
           
           案例: 用遞歸函數來給List中每個元素都加上指定前綴, 並打印加上前綴的元素 
              

def decorator(list: List[Int], prefix: String) {
if (list != Nil) {
println(prefix + list.head)
decorator(list.tail, prefix)
}
}

   3、LinkedList

           LinkedList代表一個可變的列表, 使用elem可以引用其頭部, 使用next可以引用其尾部

           val list= scala.collection.mutable.LinkedList(1, 2, 3, 4, 5) 

           list.elem

           list.next

           案例: 使用while循環將LinkedList中的每個元素都乘以2

val list= scala.collection.mutable.LinkedList(1, 2, 3, 4, 5)
var currentList =list
while (currentList != Nil) {
currentList.elem = currentList.elem * 2
currentList = currentList.next
}

       案例: 使用while循環將LinkedList中, 從第一個元素開始, 每隔一個元素, 乘以2

val list = scala.collection.mutable.LinkedList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
var currentList = list
var first = true
while (currentList != Nil && currentList.next != Nil) {
if (first) {
currentList.elem = currentList.elem * 2;
first = false
} 
currentList = currentList.next.next if (currentList != Nil) currentList.elem = currentList.elem * 2 }

  4、Set代表一個沒有重復元素的集合

          將重復元素加入Set是沒有用的, 比如val s = Set(1, 2, 3); s + 1; s + 4

          而且Set是不保證插入順序的, 也就是說, Set中的元素是亂序的,   val s = new scala.collection.mutable.HashSet[Int](); s += 1; s += 2; s += 5
          LinkedHashSet會用一個鏈表維護插入順序,      val s = new scala.collection.mutable.LinkedHashSet[Int](); s+= 1; s += 2; s += 5
           SrotedSet會自動根據key來進行排序,    val s = scala.collection.mutable.SortedSet("orange", "apple", "banana")
     5、集合的函數式編程

         Scala的集合類的mapflatMapreducereduceLeftforeach等這些函數, 就是高階函數,  因為可以接收其他函數作為參數。
         高階函數的使用, 也是ScalaJava最大的一點不同。 因為Java里面是沒有函數式編程的, 也肯定沒有  高階函數, 也肯定無法直接將函數傳入一個方法, 或者讓一個方法返回一個函數 

         Scala高階函數的理解、 掌握和使用, 可以大大增強你的技術, 而且也是Scala最有誘惑力、 最有優勢  的一個功能。

         此外, 在Spark源碼中, 有大量的函數式編程, 以及基於集合的高階函數的使用。

 

         map案例實戰: 為List中每個元素都添加一個前綴     List("Leo", "Jen", "Peter", "Jack").map("name is " + _)
         faltMap案例實戰: 將List中的多行句子拆分成單詞     List("Hello World", "You Me").flatMap(_.split(" "))
         foreach案例實戰: 打印List中的每個單 詞                List("I", "have", "a", "beautiful", "house").foreach(println(_))
         zip案例實戰: 對學生姓名和學生成績進行關聯             List("Leo", "Jen", "Peter", "Jack").zip(List(100, 90, 75, 83))

    6、函數式編程綜合案例:統計多個文本內的單詞總數

        使用scalaio包將文本文件內的數據讀取出來

         val lines01 = scala.io.Source.fromFile("C://Users//Administrator//Desktop//test01.txt").mkString

         val lines02 = scala.io.Source.fromFile("C://Users//Administrator//Desktop//test02.txt").mkString

        使用List的伴生對象, 將多個文件內的內容創建為一個List

        val lines = List(lines01, lines02)

         Scala編程的精髓是函數式編程, 也是Scala相較於Java等編程語言最大的功能優勢所在。   Spark的源碼中大量使用了這種復雜的鏈式調用的函數式編程。
         Spark本身提供的開發人員使用的編程API的風格, 完全沿用了Scala的函數式編程, 比如Spark自身的API中就提供  mapflatMapreduceforeach, 以及更高級的reduceByKeygroupByKey等高階函數
        如果要使用Scala進行Spark工程的開發, 那么就必須掌握這種復雜的高階函數的鏈式調用

          lines.flatMap(_.split(" ")).map((_, 1)).map(_._2).reduceLeft(_ + _)                         --------(_, 1)每個單詞記1; (_._2)取出1這個數

三、模式匹配

       模式匹配是Scala中非常有特色, 非常強大的一種功能。  模式匹配, 其實類似於Java中的swich case語法, 即對一個值進行條件判斷, 然后針對不同的條件, 進  行不同的處理。
       但是Scala的模式匹配的功能比Javaswich case語法的功能要強大地多, Javaswich case語法只能對   值進行匹配。
      Scala的模式匹配除了可以對值進行匹配之外, 還可以對類型進行匹配、 對ArrayList的元素情況進行匹   配、 對case class( 樣例類) 進行匹配、 甚至對有值或沒值( Option) 進行匹配。
      對於Spark來說, Scala的模式匹配功能也是極其重要的, 在Spark源碼中大量地使用了模式匹配功能 。

      1、模式匹配

           Scala是沒有Java中的switch case語法的, 相對應的, Scala提供了更加強大的match case語法, 即模式匹配。  Scalamatch caseJavaswitch case最大的不同點在於, Javaswitch case

僅能匹配變量的值, 比12、 3等; 而Scalamatch case可以匹配各種情況, 比如變量的類型、 集合的元素、 有值或無值 

          match case的語法如下: 變量 match { case => 代碼 }

          如果值為下划線, 則代表了不滿足以上所有情況下的默認情況如何處理

           此外, match case中, 只要一個case分支滿足並處理了, 就不會繼續判斷下一個case分支了。  ( 與Java不同, javaswitch case需要用break阻止)
          match case語法最基本的應用, 就是對變量的值進行模式匹配     例:成績評價

            

def judgeGrade(grade: String) {
grade match {
case "A" => println("Excellent")
case "B" => println("Good")
case "C" => println("Just so so")
case _ => println("you need work harder")
}
}

   2、在模式匹配中使用if守衛

         Scala的模式匹配語法, 有一個特點在於, 可以在case后的條件判斷中, 不僅僅只是提供一個值,  而是可以在值后面再加一個if守衛, 進行雙重過濾

def judgeGrade(name: String, grade: String) {
grade match {
case "A" => println(name + ", you are excellent")
case "B" => println(name + ", you are good")
case "C" => println(name + ", you are just so so")
case _ if name == "leo" => println(name + ", you are a good boy, come on")     //前三種不符合,如果name=leo  則輸出這個
case _ => println("you need to work harder")
}
}

  3、在模式匹配中進行變量賦值

          Scala的模式匹配語法, 有一個特點在於, 可以將模式匹配的默認情況, 下划線, 替換為一個變量名。  此時模式匹配語法就會將要匹配的值賦值給這個變量, 從而可以在后面的處理語句中使用要匹配的值。
       

def judgeGrade(name: String, grade: String) {
grade match {
case "A" => println(name + ", you are excellent")
case "B" => println(name + ", you are good")
case "C" => println(name + ", you are just so so")
case _grade if name == "leo" => println(name + ", you are a good boy, come on, your grade is " + _grade)
case _grade => println("you need to work harder, your grade is " + _grade)
}
}

  4、對類型進行模式匹配

          Scala的模式匹配一個強大之處就在於, 可以直接匹配類型, 而不是值。   這點是Javaswitch case絕對做不到的。
           匹配類型的話, 需要用“ case 變量 : 類型 => 代碼” 這種語法, 而不是匹配值的“ case => 代碼” 這種語法。

           案例:異常處理    

import java.io._
def processException(e: Exception) {
e match {
case e1: IllegalArgumentException => println("you have illegal arguments! exception is: " + e1)
case e2: FileNotFoundException => println("cannot find the file you need read or write!, exception is: " + e2)
case e3: IOException => println("you got an error while you were doing IO operation! exception is: " + e3)
case _: Exception => println("cannot know which exception you have!" )
}
}

  調用時:      processException(new IOException("liu"))

      5、對Array和List進行模式匹配 

          Array進行模式匹配, 分別可以匹配:    帶有指定元素的數組、 帶有指定個數元素的數組、 以某元素打頭的數組

def greeting(arr: Array[String]) {
arr match {
case Array("Leo") => println("Hi, Leo!")
case Array(girl1, girl2, girl3) => println("Hi"+girl1 + " and " + girl2 + " and " + girl3)
case Array("Leo", _*) => println("Hello, Leo")
case _ => println("hey, who are you?")
}
}

     List進行模式匹配, 與Array類似, 但是需要使用List特有的::操作符 

def greeting(list: List[String]) {
list match {
case "Leo" :: Nil => println("Hi, Leo!")
case girl1 :: girl2 :: girl3 :: Nil => println("Hi " + girl1 + " and " + girl2 + " and " + girl3)
case "Leo" :: tail => println("Hi, Leo.")
case _ => println("hey, who are you?")
}
}

  6、case class(樣例類)與模式匹配
         Scala中提供了一種特殊的類, 用case class進行聲明, 中文也可以稱作樣例類。
       case class其實有點類似於Java中的JavaBean的概念, 即只定義field, 並且由Scala編譯時   自動提供gettersetter方法, 但是沒有method
         case class的主構造函數接收的參數通常不需要使用varval修飾, Scala自動就會使用  val修飾。
         Scala自動為case class定義了伴生對象, 也就是object, 並且定義了apply()方法, 該方   法接收主構造函數中相同的參數, 並返回case class對象
           案例:
             

class Person
case class Teacher(name: String, subject: String) extends Person
case class Student(name: String, classroom: String) extends Person
def judgeIdentify(p: Person) {
p match {
case Teacher(name, subject) => println("Teacher, name is " + name + ", subject is " + subject)
case Student(name, classroom) => println("Student, name is " + name + ", classroom is " +
classroom)
case _ => println("Illegal access, please go out of the school!")
}
}

  7、Option與模式匹配

           Scala有一種特殊的類型, 叫做Option。  Option有兩種值, 一種是Some, 表示有值, 一種是None, 表示沒有值。
           Option通常會用於模式匹配中, 用於判斷某個變量是有值還是沒有值, 這比null來的更加簡潔明了

            案例: 成績查詢                  

val grades = Map("Leo" -> "A", "Jack" -> "B", "Jen" -> "C")
def getGrade(name: String) {
val grade = grades.get(name)
grade match {
case Some(grade) => println("your grade is " + grade)
case None => println("Sorry!")
}
}

   

四、類型參數

     1、泛型類

          泛型類, 顧名思義, 其實就是在類的聲明中, 定義一些泛型類型, 然后在類內部, 比如字段或者方法, 就可以使用  這些泛型類型。 

           使用泛型類, 通常是需要對類中的某些成員, 比如某些字段和方法中的參數或變量, 進行統一的類型限制, 這樣可  以保證程序更好的健壯性和穩定性。 

           如果不使用泛型進行統一的類型限制, 那么在后期程序運行過程中, 難免會出現問題, 比如傳入了不希望的類型,  導致程序出問題。  

             在使用類的時候, 比如創建類的對象, 將類型參數替換為實際的類型, 即可

             Scala自動推斷泛型類型特性: 直接給使用了泛型類型的字段賦值時, Scala會自動進行類型推斷。      

案例: 新生報到, 每個學生來自不同的地方, id可能是Int, 可能是String
class Student[T](val localId: T) {
def getSchoolId(hukouId: T) = "S-" + hukouId + "-" + localId
} 
val leo = new Student[Int](111)
val jack=new Student(1)

   2、泛型函數

           泛型函數, 與泛型類類似, 可以給某個函數在聲明時指定泛型類型, 然后在函數體內, 多個變量或者  返回值之間, 就可以使用泛型類型進行聲明, 從而對某個特殊的變量, 或者多個變量, 進行強制性的類  型限制
           與泛型類一樣, 你可以通過給使用了泛型類型的變量傳遞值來讓Scala自動推斷泛型的實際類型, 也可  以在調用函數時, 手動指定泛型類型
          

案例: 卡片售賣機, 可以指定卡片的內容, 內容可以是String類型或Int類型
def getCard[T](content: T) = {
if(content.isInstanceOf[Int]) "card: 001, " + content
else if(content.isInstanceOf[String]) "card: this is your card, " + content
else "card: " + content
}
getCard[String]("hello world")

  3、協變和逆變

         Scala的協變和逆變是非常有特色的! 完全解決了Java中的泛型的一大缺憾!

          舉例來說, Java中, 如果有ProfessionalMaster的子類, 那么Card[Professionnal]是不是Card[Master]    的子類? 答案是: 不是。 因此對於開發程序造成了很多的麻煩
        Scala中, 只要靈活使用協變和逆變, 就可以解決Java泛型的問題。 
     

 協變 案例: 進入會場
class Master
class Professional extends Master
// 大師以及大師級別以下的名片都可以進入會場
class Card[+T] (val name: String)
def enterMeet(card: Card[Master]) {
println("welcome to have this meeting!")
}

  調用時:val  a=new Card[Master]("liu")         enterMeet(a)

                val  b=new Card[Professional]("liu")      enterMeet(b)

 

    逆變案例:只要專家級別的名片就可以進入會場, 如果大師級別的過來了, 當然可以了!

class Card[-T] (val name: String)
def enterMeet(card: Card[Professional]) {
println("welcome to have this meeting!")
}

五、隱式轉換與隱式參數

      Scala提供的隱式轉換和隱式參數功能, 是非常有特色的功能, 是Java等編程語言所沒有的功能。 它可以允許你手動指定, 將某種類型的對象轉換成其他類型的對象。 通過這些功能, 可以實現非常強
大, 而且特殊的功能。

      Scala的隱式轉換, 其實最核心的就是定義隱式轉換函數, 即implicit conversion function

       定義的隱式轉換函數, 只要在編寫的程序內引入, 就會被Scala自動使用。

       Scala會根據隱式轉換函數的簽名, 在程序中使用到隱式轉換函數接收的參數類型定義的對象時, 會自  動將其傳入隱式轉換函數, 轉換為另外一種類型的對象並返回。 這就是“隱式轉換” 。 

       隱式轉換函數叫什么名字是無所謂的, 因為通常不會由用戶手動調用, 而是由Scala進行調用。

       但是如果要使用隱式轉換, 則需要對隱式轉換函數進行導入。 因此通常建議將隱式轉換函數的名稱命   名為“ one2one” 的形式。 

    1、隱式轉換——隱式函數   

class Num()
class RichNum(num:Num){
      def rich{
           println("hi!")
}
}
object Implic{
       implicit  def Num2RichNum(num:Num)=new RichNum(num)
      def main(args:Array[String]) : Unit={
           val  num =new Num
            num.rich
}
}
對象num並沒有rich方法,編譯器會查找
當前范圍內是否有可轉換的方法,如果沒
有則編譯失敗。

  

object Implic2{
    implicit def int2String(i:Int)=i.toString()
def main(args:Array[String]) : Unit={
println(5.length())
}
}

 代碼中調用了String類型的length方法,Int類型本身沒有length方法,但是在可用范圍  內定義了可以把Int轉換為String的隱式函數int2String,因此函數編譯通過並運行出正 確的結果。
   此實例中隱式函數的定義必須定義在使用之前,否則編譯報錯。

        2、隱式轉換——導入隱式函數
            

import ImplicitPro.Int2StringTest._
object ImplicitTest{
def main(args:Array[String]) : Unit={
println(4.length())
}
}

  

       3、隱式轉換

          要實現隱式轉換, 只要程序可見的范圍內定義隱式轉換函數即可。 Scala會自動使用隱式轉換函數。

         隱式轉換函數與普通函數唯一的語法區別就是, 要以implicit開頭, 而且最好要定義函數返回類型。

           

// 案例: 特殊售票窗口( 只接受特殊人群, 比如學生、 老人等)
class SpecialPerson(val name: String)
class Student(val name: String)
class Older(val name: String)
implicit def object2SpecialPerson (obj: Object): SpecialPerson = {
if (obj.getClass == classOf[Student]) { val stu = obj.asInstanceOf[Student]; new SpecialPerson(stu.name) }
else if (obj.getClass == classOf[Older]) { val older = obj.asInstanceOf[Older]; new SpecialPerson(older.name) }
else Nil
}
var ticketNumber = 0
def buySpecialTicket(p: SpecialPerson) = {
ticketNumber += 1
"T-" + ticketNumber
}

   4、使用隱式轉換加強現有類型

         隱式轉換非常強大的一個功能, 就是可以在不知不覺中加強現有類型的功能。

        也就是說, 可以為某個類定義一個加強版的類, 並定義互相之間的隱式轉換, 從而讓源類在使用加強版  的方法時, 由Scala自動進行隱式轉換為加強類, 然后再調用該方法
          

// 案例: 超人變身
class Man(val name: String)
class Superman(val name: String) {
def emitLaser = println("emit a laster!")
} 
implicit def man2superman(man: Man): Superman = new Superman(man.name)
val leo = new Man("leo")
leo.emitLaser

  5、隱式參數

          所謂的隱式參數, 指的是在函數或者方法中, 定義一個用implicit修飾的參數, 此時Scala會嘗試找  到一個指定類型的, 用implicit修飾的對象, 即隱式值, 並注入參數。
         Scala會在兩個范圍內查找:
               一種是當前作用域內可見的valvar定義的隱式變量;
               一種是隱式參數類型的伴生對象內的隱式值

// 案例: 考試簽到
class SignPen {
def write(content: String) = println(content)
} 
implicit val signPen = new SignPen    //定義隱式值
def signForExam(name: String) (implicit signPen: SignPen) {              //()()柯里化函數,第二個參數是一個隱式參數,scala系統會自動在代碼范圍內尋找相應隱式值,找到相應的隱式值之后,會自動將隱式
signPen.write(name + " come to exam in time.")                                //   值賦給隱式參數,不需要手動賦值,隱式參數的類型與隱式值一致
}

  調用    signForExam("liu")

六、閉包

            閉包最簡潔的解釋: 函數在變量不處於其有效作用域時, 還能夠對變量進行訪問, 即為閉包  

            閉包:某個變量超出了其作用 域范圍,但仍然可以使用      

def getGreetingFunc(msg: String) = (name: String) => println(msg + ", " + name)
val greetingFuncHello = getGreetingFunc("hello")
val greetingFuncHi = getGreetingFunc("hi")

       兩次調用getGreetingFunc函數, 傳入不同的msg, 並創建不同的函數返回。    但是, msg只是一個局部變量, 這種變量超出了其作用域, 還可以使用的情況, 即為閉包。
七、Currying(柯里化)函數

 Curring函數, 指的是, 將原來接收兩個參數的一個函數, 轉換為兩個函數, 第一個函數接收原先的第一個參數, 然后返回接收原先第二個參數的第二個函數 

在函數調用的過程中, 就變為了兩個函數連續調用的形式。  Spark的源碼中, 對於()()這種形式很常見。

def sum(a: Int, b: Int) = a + b
sum(1, 1)
def sum3(a: Int)(b: Int) = a + b
sum3(1)(1)

 

 

八、Actor

        ScalaActor類似於Java中的多線程編程。 但是不同的是, ScalaActor提供的模型與多線程有所  不同。 ScalaActor盡可能地避免鎖和共享狀態, 從而避免多線程並發時出現資源爭用的情況, 進
而提升多線程編程的性能。 此外, Scala Actor的這種模型還可以避免死鎖等一系列傳統多線程編程 的問題 

          Spark中使用的分布式多線程框架, 是AkkaAkka也實現了類似Scala Actor的模型, 其核心概念 同樣也是Actor。 因此只要掌握了Scala Actor, 那么在Spark源碼研究時, 至少即可看明白Akka
Actor相關的代碼。 但是, 換一句話說, 由於Spark內部有大量的Akka Actor的使用, 因此對於 Scala Actor也至少必須掌握, 這樣才能學習Spark源碼。 

      1、Actor的創建、啟動和消息收發

           Scala提供了Actor trait來讓我們更方便地進行actor多線程編程, Actor trait就類似於 Java中的ThreadRunnable一樣, 是基礎的多線程基類和接口 

          我們只要重寫Actor traitact方法, 即可實現自己的線程執行體, 與Java中重寫run方  法類似。
          此外, 使用start()方法啟動actor;    使用!符號, 向actor發送消息;   actor內部使用receive和模式匹配接收消息
 

// 案例: Actor Hello World
import scala.actors.Actor
class HelloActor extends Actor {
def act() {
while (true) {
receive {
case name: String => println("Hello, " + name)
}
}
}
}
val helloActor = new HelloActor
helloActor.start()
helloActor ! "leo"

    2、收發case class類型的消息

          ScalaActor模型與Java的多線程模型之間, 很大的一個區別就是, Scala  Actor天然支持線程之間的精准通信; 即一個actor可以給其他actor直接發送消息。 這個功能是非常強大和方便的。

        要給一個actor發送消息, 需要使用“ actor ! 消息” 的語法。 在scala中, 通常建  議使用樣例類, 即case class來作為消息進行發送。 然后在actor接收消息之后,  可以使用scala強大的模式匹配功能來

進行不同消息的處理。
         

// 案例: 用戶注冊登錄后台接口
case class Login(username: String, password: String)
case class Register(username: String, password: String)
class UserManageActor extends Actor {
def act() {
while (true) {
receive {
case Login(username, password) => println("login, username is " + username + ", password is " + password)
case Register(username, password) => println("register, username is " + username + ", password is " +
password)
}
}
}
} 
val userManageActor = new UserManageActor
userManageActor.start()
userManageActor ! Register("leo", "1234"); userManageActor ! Login("leo", "1234")

    3、Actor之間互相收發消息
              如果兩個Actor之間要互相收發消息, 那么Scala的建議是, 一個actor向另外一個actor發   送消息時, 同時帶上自己的引用; 其他actor收到自己的消息時, 直接通過發送消息的
actor的引用, 即可以給它回復消息。
          

// 案例: 打電話
import scala.actors.Actor
case class Message(content: String, sender: Actor)
class LeoTelephoneActor extends Actor {
def act() {
while (true) {
receive {
case Message(content, sender) => {
println("leo telephone: " + content); sender ! "I'm leo, please call me after 10 minutes." }
}
}
}
}


class JackTelephoneActor(val leoTelephoneActor: Actor) extends Actor {
def act() {
leoTelephoneActor ! Message("Hello, Leo, I'm Jack.", this)
receive {
case response: String => println("jack telephone: " + response)
}
}
}


最后main方法:

val c=new LeoTelephoneActor 

val cc=new JackTelephoneActor(c)

c.start()
cc.start()

 

補充:在spark中

        1、lines.map(x=>x.split(" ")).collect 結果一行一個array,x代表每一行
        2、lines.flatMap() 結果一個array, Array(hello,hadoop,.....)
              flatMap:flatten map 先執行map,后執行flatten(扁平化)

         3、lines.map(x=>x.split("\t")(2))     取出第三個字段的所有值

         4、lines.first   取出第一條數據

         5、lines.map(x=>x.split("\t")).filter(x=>x.length==6)  過濾

            統計上午7到10點搜索過百度影音的客戶ID 

             .filter(x=>x.length==6 && 7<= <10 && kw.contains("百度影音"))
             .map(x=>x(1))

         6、val tupple=("zahngsan",(10,90))

              tupple._1 zhangsan
              tupple._2._1 10
              tupple._2._2 90

         7、 軟件開發的生命周期: 

               需求分析

               概要設計

                詳細設計
                代碼編寫(web前端、Java后台、大數據開發、數據庫運維、服務器運維)
                運行測試
                發布部署
                維護升級




              
   

              



    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM