【Scala篇】--Scala中Trait、模式匹配、樣例類、Actor模型

LHBlog發表於2018-02-01

一、前述

Scala Trait(特徵) 相當於 Java 的介面,實際上它比介面還功能強大。

模式匹配機制相當於java中的switch-case。

使用了case關鍵字的類定義就是樣例類(case classes),樣例類是種特殊的類。

Actor相當於Java中的多執行緒。

二、具體闡述

trait特性

     1、概念理解

Scala Trait(特徵) 相當於 Java 的介面,實際上它比介面還功能強大。

與介面不同的是,它還可以定義屬性和方法的實現。

一般情況下Scala的類可以繼承多個Trait,從結果來看就是實現了多重繼承。Trait(特徵) 定義的方式與類類似,但它使用的關鍵字是 trait

   2、舉例:trait中帶屬性帶方法實現

  • 繼承的多個trait中如果有同名的方法和屬性,必須要在類中使用“override”重新定義。
  • trait中不可以傳參。
trait Read {
  val readType = "Read"
  val gender = "m"
  def read(name:String){
	println(name+" is reading")
  }
}

trait Listen {
  val listenType = "Listen"
  val gender = "m"
  def listen(name:String){
	println(name + " is listenning")
  }
}

class Person() extends Read with Listen{
  override val gender = "f"
}

object test {
  def main(args: Array[String]): Unit = {
    val person = new Person()
    person.read("zhangsan")
    person.listen("lisi")
    println(person.listenType)
    println(person.readType)
    println(person.gender)
    
  }
}

 

 3、舉例:trait中帶方法不實現

 

object Lesson_Trait2 {
  def main(args: Array[String]): Unit = {
    val p1 = new Point(1,2)
    val p2 = new Point(1,3)
    println(p1.isEqule(p2))
    println(p1.isNotEqule(p2))
  }
}

trait Equle{
  def isEqule(x:Any) :Boolean 
  def isNotEqule(x : Any)  = {
    !isEqule(x)
  }
}

class Point(x:Int, y:Int) extends Equle {
  val xx = x
  val yy = y

  def isEqule(p:Any) = {
    p.isInstanceOf[Point] && p.asInstanceOf[Point].xx==xx
  }
  
}

 

 模式匹配match

      1、概念理解:

         Scala 提供了強大的模式匹配機制,應用也非常廣泛。

        一個模式匹配包含了一系列備選項,每個都開始於關鍵字 case

        每個備選項都包含了一個模式及一到多個表示式。箭頭符號 => 隔開了模式和表示式。

 

     2、程式碼及注意點

  • 模式匹配不僅可以匹配值還可以匹配型別
  • 從上到下順序匹配,如果匹配到則不再往下匹配
  • 都匹配不上時,會匹配到case _ ,相當於default
  • match 的最外面的”{ }”可以去掉看成一個語句
object Lesson_Match {
  def main(args: Array[String]): Unit = {
    val tuple = Tuple6(1,2,3f,4,"abc",55d)
    val tupleIterator = tuple.productIterator
    while(tupleIterator.hasNext){
      matchTest(tupleIterator.next())
    }
    
  }
  /**
   * 注意點:
   * 1.模式匹配不僅可以匹配值,還可以匹配型別
   * 2.模式匹配中,如果匹配到對應的型別或值,就不再繼續往下匹配
   * 3.模式匹配中,都匹配不上時,會匹配到 case _ ,相當於default
   */
  def matchTest(x:Any) ={
    x match {
      case x:Int=> println("type is Int")
      case 1 => println("result is 1")
      case 2 => println("result is 2")
      case 3=> println("result is 3")
      case 4 => println("result is 4")
      case x:String => println("type is String")
//      case x :Double => println("type is Double")
      case _ => println("no match")
    }
  }
  
}

 樣例類(case classes)

1、概念理解

     使用了case關鍵字的類定義就是樣例類(case classes),樣例類是種特殊的類。實現了類構造引數的getter方法(構造引數預設被宣告為val),當構造引數是宣告為var型別時,它幫你實現settergetter方法。

  • 樣例類預設幫你實現了toString,equalscopyhashCode等方法。
  • 樣例類可以new, 也可以不用new

2、例子:結合模式匹配的程式碼

case class Person1(name:String,age:Int)

object Lesson_CaseClass {
  def main(args: Array[String]): Unit = {
    val p1 = new Person1("zhangsan",10)
    val p2 = Person1("lisi",20)
    val p3 = Person1("wangwu",30)
    
    val list = List(p1,p2,p3)
    list.foreach { x => {
      x match {
        case Person1("zhangsan",10) => println("zhangsan")
        case Person1("lisi",20) => println("lisi")
        case _ => println("no match")
      }
    } }
    
  }
}

 

 Actor Model

1、概念理解

Actor Model是用來編寫平行計算或分散式系統的高層次抽象(類似java中的Thread)讓程式設計師不必為多執行緒模式下共享鎖而煩惱,被用在Erlang 語言上, 高可用性99.9999999 % 一年只有31ms 當機Actors將狀態和行為封裝在一個輕量的程式/執行緒中,但是不和其他Actors分享狀態,每個Actors有自己的世界觀,當需要和其他Actors互動時,通過傳送事件和訊息,傳送是非同步的,非堵塞的(fire-andforget),傳送訊息後不必等另外Actors回覆,也不必暫停,每個Actors有自己的訊息佇列,進來的訊息按先來後到排列,這就有很好的併發策略和可伸縮性,可以建立效能很好的事件驅動系統。

Actor的特徵:

  • ActorModel是訊息傳遞模型,基本特徵就是訊息傳遞
  • 訊息傳送是非同步的,非阻塞的
  • 訊息一旦傳送成功,不能修改
  • Actor之間傳遞時,自己決定決定去檢查訊息,而不是一直等待,是非同步非阻塞的

2、什麼是Akka

Akka 是一個用 Scala 編寫的庫,用於簡化編寫容錯的、高可伸縮性的 Java Scala Actor 模型應用,底層實現就是Actor,Akka是一個開發庫和執行環境,可以用於構建高併發、分散式、可容錯、事件驅動的基於JVM的應用。使構建高併發的分散式應用更加容易。

spark1.6版本之前,spark分散式節點之間的訊息傳遞使用的就是Akka,底層也就是actor實現的。1.6之後使用的netty傳輸。

3、例:Actor簡單例子傳送接收訊息

 

import scala.actors.Actor

class myActor extends Actor{
  
  def act(){
    while(true){
      receive {
        case x:String => println("save String ="+ x)
        case x:Int => println("save Int")
        case _ => println("save default")
      }
    }
  }
}

object Lesson_Actor {
  def main(args: Array[String]): Unit = {
    
    //建立actor的訊息接收和傳遞
    val actor =new myActor()
    //啟動
    actor.start()
    //傳送訊息寫法
    actor ! "i love you !"

  }
}

 

 4、例:ActorActor之間通訊

 

 

case class Message(actor:Actor,msg:Any)

class Actor1 extends Actor{
  def act(){
    while(true){
      receive{
        case  msg :Message => {
          println("i sava msg! = "+ msg.msg)
          
          msg.actor!"i love you too !"
          }
        case msg :String => println(msg)
        case  _ => println("default msg!")
      }
    }
  }
}

class Actor2(actor :Actor) extends Actor{
  actor ! Message(this,"i love you !")
	def act(){
		while(true){
			receive{
  			case msg :String => {
  			  if(msg.equals("i love you too !")){
  			    println(msg)
  			   actor! "could we have a date !"
  			  }
  			}
  			case  _ => println("default msg!")
			}
		}
	}
}

object Lesson_Actor2 {
  def main(args: Array[String]): Unit = {
    val actor1 = new Actor1()
    actor1.start()
    val actor2 = new Actor2(actor1)
    actor2.start()
  }
}

 附例:WordCount

import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.rdd.RDD
import org.apache.spark.rdd.RDD.rddToPairRDDFunctions

object WordCount {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf()
    conf.setMaster("local").setAppName("WC")
    val sc = new SparkContext(conf)
    val lines :RDD[String] = sc.textFile("./words.txt")
    val word :RDD[String]  = lines.flatMap{lines => {
      lines.split(" ")
    }}
    val pairs : RDD[(String,Int)] = word.map{ x => (x,1) }
    val result = pairs.reduceByKey{(a,b)=> {a+b}}
    result.sortBy(_._2,false).foreach(println)
    
    //簡化寫法
    lines.flatMap { _.split(" ")}.map { (_,1)}.reduceByKey(_+_).foreach(println)
    
  }
}

 

 

 

相關文章