Scala學習筆記

Scala介紹

首先Scala是一門基於JVM的編程語言,具有很好的兼容性和併發性。

Scala六大特徵

  1. Java和Scala可以無縫混編
  2. 類型推測(自動推測類型)
  3. 併發和分佈式
  4. 特質trait,特徵(類似於java中interface和abstract結合,可以實現多繼承)
  5. 模式匹配(類似於java switch)
  6. 高階函數(包含兩種:①函數的參數是函數②函數的返回是函數)

Scala的安裝與配置

1,下載安裝包

官網下載scala2.10:https://www.scala-lang.org/download/2.10.4.html 

2,配置環境變量(和配置jdk相似)

//首先配置SCALA_HOME
SCALA_HOME=“scala的解壓路徑”
//然後配置path
;%SCALA_HOME%\bin;%SCALA_HOME%\jre\bin

3,編譯器配置
3.1,eclipse配置Scala插件

下載插件(一定要對應eclipse版本下載)
http://scala-ide.org/download/prev-stable.html  

解壓後把features和plugins兩個文件夾拷貝到eclipse安裝目錄中的” dropins/scala”目錄下。
3.2,或者使用scala ide

下載網址:http://scala-ide.org/download/sdk.html 

3.3,idea中配置scala插件
①打開idea,close項目後,點擊Configure->Plugins
②搜索scala,點擊安裝
③設置jdk,打開Project Structure,點擊new 選擇安裝好的jdk路徑
④創建scala項目,配置scala sdk(Software Development Kit)

Scala基礎

1,數據類型

在這裏插入圖片描述
在這裏插入圖片描述在這裏插入圖片描述

2,變量與常量的聲明

變量:用var定義,可修改
常量:用val定義,不可修改
例子:
var name="zhangsan"
val gender="man"

3,類和對象

創建類
class Person{
  val name = "zhangsan"
  val age = 18
  def sayName() = {
    "my name is "+ name
  }
}

創建對象
object Lesson_Class {
   def main(args: Array[String]): Unit = {
    val person = new Person()
    println(person.age);
    println(person.sayName())
  }
}



伴生類和伴生對象
	class Person(xname :String , xage :Int){
  var name = Person.name
  val age = xage
  var gender = "m"
  def this(name:String,age:Int,g:String){
    this(name,age)
    gender = g
  }
  
  def sayName() = {
    "my name is "+ name
  }
}

object Person {
  val name = "zhangsanfeng"
  
  def main(args: Array[String]): Unit = {
    val person = new Person("wagnwu",10,"f")
    println(person.age);
    println(person.sayName())
    println(person.gender)
  }
}

注意apply方法的使用:apply方法是在類加載的時候啓動放入,所以可以初始化一些信息,例如:我們在apply方法中new 對象,那麼在我們main方法中實例化對象中省去new。

object ScalaDemo01 {
  def main(args: Array[String]): Unit = {
    val p = new Person("zs",19)
     val person = Person("wagnwu",10)
  }
}

class Person(xname :String , xage :Int){
  val name = "zs"
  val age = xage
  var gender = "m"
  def this(name:String,age:Int,g:String){
    this(name,age)
    gender = g
  }
}

object Person{
  def apply(name:String,age:Int)={
    new Person(name,age)
  }
}

注意事項:

  • 建議類名首字母大寫 ,方法首字母小寫,類和方法命名建議符合駝峯命名法。
  • scala 中的object是單例對象,相當於java中的工具類,可以看成是定義靜態的方法的類。object不可以傳參數。另:Trait不可以傳參數
  • scala中的class類默認可以傳參數,默認的傳參數就是默認的構造函數。
    重寫構造函數的時候,必須要調用默認的構造函數。
  • class 類屬性自帶getter ,setter方法。
  • 使用object時,不用new,使用class時要new ,並且new的時候,class中除了方法不執行,其他都執行。
  • 如果在同一個文件中,object對象和class類的名稱相同,則這個對象就是這個類的伴生對象,這個類就是這個對象的伴生類。可以互相訪問私有變量。

4,if else的使用

 /**
 * if else 
 */
val age =18 
if (age < 18 ){
	println("no allow")
}else if (18<=age&&age<=20){
	println("allow with other")
}else{
	println("allow self")
}

5,for ,while,do…while的使用

  /**
     * to和until
     * 例:
     * 1 to 10 返回1到10的Range數組,包含10
     * 1 until 10 返回1到10 Range數組 ,不包含10
  */

println(1 to 10 )//打印 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
println(1.to(10))//與上面等價,打印 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

println(1 to (10 ,2))//步長爲2,從1開始打印 ,1,3,5,7,9
println(1.to(10, 2)) 

println(1 until 10 ) //不包含最後一個數,打印 1,2,3,4,5,6,7,8,9
println(1.until(10))//與上面等價
    
println(1 until (10 ,3 ))//步長爲2,從1開始打印,打印1,4,7

6,創建for循環

for( i <- 1 to 10 ){
  println(i)
}

7,創建多層for循環

   var count = 0;
    for(i <- 1 to 10; j <- 1 until 10){
      println("i="+ i +",	j="+j)
      count += 1
    }
    println(count);
    
    //例子: 打印小九九
    for(i <- 1 until 10 ;j <- 1 until 10){
      if(i>=j){
    	  print(i +" * " + j + " = "+ i*j+"	")
        
      }
      if(i==j ){
        println()
      }
      
    }

8,帶判斷條件的for循環

  for(i<- 1 to 10 ;if (i%2) == 0 ;if (i == 4) ){
      println(i)
}

9. scala中不能使用count++,count—只能使用count = count+1 ,count += 1

10. for循環用yield 關鍵字返回一個集合

11. while循環,while(){},do {}while()

Scala函數

  • 函數定義語法 用def來定義
  • 可以定義傳入的參數,要指定傳入參數的類型
  • 方法可以寫返回值的類型也可以不寫,會自動推斷,有時候不能省略,必須寫,比如在遞歸函數中或者函數的返回值是函數類型的時候。
  • scala中函數有返回值時,可以寫return,也可以不寫return,會把函數中最後一行當做結果返回。當寫return時,必須要寫函數的返回值。
  • 如果返回值可以一行搞定,可以將{}省略不寫
  • 傳遞給方法的參數可以在方法中使用,並且scala規定方法的傳過來的參數爲val的,不是var的。
  • 如果去掉方法體前面的等號,那麼這個方法返回類型必定是Unit的。這種說法無論方法體裏面什麼邏輯都成立,scala可以把任意類型轉換爲Unit.假設,裏面的邏輯最後返回了一個string,那麼這個返回值會被轉換成Unit,並且值會被丟棄。

scala幾大函數

  • 普通函數
  • 帶默認值的函數
  • 遞歸函數
  • 可變參數個數的函數
  • 匿名函數
  • 嵌套函數
  • 偏應用函數
  • 高階函數
  • 柯里化函數

1,普通函數

def fun (a: Int , b: Int ) : Unit = {
   println(a+b)
 }
fun(1,1)
    
def fun1 (a : Int , b : Int)= a+b
 println(fun1(1,2))  

2,遞歸函數

 /**
     * 遞歸函數 
     * 5的階乘
     */
    def fun2(num :Int) :Int= {
      if(num ==1)
        num
      else 
        num * fun2(num-1)
    }
    print(fun2(5))

3, 帶默認值的函數

 def fun3(a :Int = 10,b:Int) = {
      println(a+b)
    }
    fun3(b=2)

4,可變參數個數的函數

def fun4(elements :Int*)={
      var sum = 0;
      for(elem <- elements){
        sum += elem
      }
      sum
    }
    println(fun4(1,2,3,4))

5,匿名函數

   //有參數匿名函數
    val value1 = (a : Int) => {
      println(a)
    }
    value1(1)
    
    //無參數匿名函數
    val value2 = ()=>{
      println("我愛Angelababy")
    }
    value2()
    
    //有返回值的匿名函數
    val value3 = (a:Int,b:Int) =>{
      a+b
    }
    println(value3(4,4))

6,嵌套函數

def fun5(num:Int)={
      def fun6(a:Int,b:Int):Int={
        if(a == 1){
          b
        }else{
          fun6(a-1,a*b)
        }
      }
      fun6(num,1)
    }
    println(fun5(5))

7,偏應用函數

def log(date :Date, s :String)= {
      println("date is "+ date +",log is "+ s)
    }

val date = new Date()
log(date ,"log1")
log(date ,"log2")
log(date ,"log3")

//想要調用log,以上變化的是第二個參數,可以用偏應用函數處理
val logWithDate = log(date,_:String)
logWithDate("log11")
logWithDate("log22")
logWithDate("log33")

8,高階函數

 /**
     * 高階函數
     * 函數的參數是函數		或者函數的返回是函數		或者函數的參數和返回都是函數
     */

 //函數的參數是函數
    def hightFun(f : (Int,Int) =>Int, a:Int ) : Int = {
      f(a,100)
    }
    def f(v1 :Int,v2: Int):Int  = {
      v1+v2
    }
    
println(hightFun(f, 1))

//函數的返回是函數
//1,2,3,4相加
def hightFun2(a : Int,b:Int) : (Int,Int)=>Int = {
  def f2 (v1: Int,v2:Int) :Int = {
    v1+v2+a+b
  }
  f2
}
println(hightFun2(1,2)(3,4))

//函數的參數是函數,函數的返回是函數
def hightFun3(f : (Int ,Int) => Int) : (Int,Int) => Int = {
  f
} 
println(hightFun3(f)(100,200))
println(hightFun3((a,b) =>{a+b})(200,200))
//以上這句話還可以寫成這樣
//如果函數的參數在方法體中只使用了一次 那麼可以寫成_表示
println(hightFun3(_+_)(200,200))

9,柯里化函數

 /**
     * 柯里化函數
     */
    def fun7(a :Int,b:Int)(c:Int,d:Int) = {
      a+b+c+d
    }
    println(fun7(1,2)(3,4))

Scala字符串

  • String定長字符串

  • StringBuilder可變長度字符串

  • 常用操作方法
    比較:equals
    忽略大小寫比較:equalsIgnoreCase
    查找:indexOf,返回遊標

     val str = "abcd"
     val str1 = "ABCD"
     
     println(str.indexOf(97))
     println(str.indexOf("b"))
    
     println(str==str1)
     /**
      * compareToIgnoreCase
      * 
      * 如果參數字符串等於此字符串,則返回值 0;
      * 如果此字符串小於字符串參數,則返回一個小於 0 的值;
      * 如果此字符串大於字符串參數,則返回一個大於 0 的值。
      * 
      */
     println(str.compareToIgnoreCase(str1))
     
     val strBuilder = new StringBuilder
     strBuilder.append("abc")
     
     //strBuilder.+('d')
       strBuilder+ 'd'
     //strBuilder.++=("efg")
        strBuilder++= "efg" 
     //strBuilder.+=('h')
       strBuilder+= 'h' 
       strBuilder.append(1.0)
       strBuilder.append(18f)
       println(strBuilder)
    

Scala集合

數組

1,創建數組
new Array[Int](10) 
賦值:arr(0) = xxx
Array[String](“s1”,”s2”,”s3”)

2,數組遍歷
for
foreach
3,創建一維數組和二維數組
4,數組中方法舉例
Array.concate:合併數組
Array.fill(5)(“bjsxt”):創建初始值的定長數組

list集合

1.創建list
val list = List(1,2,3,4)
Nil長度爲0的list

2.list遍歷
foreach ,for

3.list方法舉例
filter:過濾元素
count:計算符合條件的元素個數
map:對元素操作
flatmap :壓扁扁平,先map再flat

 //創建
    val list = List(1,2,3,4,5)
    
    //遍歷
    list.foreach { x => println(x)}
//    list.foreach { println}
    //filter
    val list1  = list.filter { x => x>3 }
    list1.foreach { println}
    
    //count
    val value = list1.count { x => x>3 }
    println(value)
    
    //map
    val nameList = List(
    		"hello bjsxt",
    		"hello xasxt",
    		"hello shsxt"
        )
    val mapResult:List[Array[String]] = nameList.map{ x => x.split(" ") }
    mapResult.foreach{println}    
    
    //flatmap
    val flatMapResult : List[String] = nameList.flatMap{ x => x.split(" ") }
    flatMapResult.foreach { println }

set集合

  1. 創建set
    注意:set集合會自動去重
  2. set遍歷
    foreach,for
  3. set方法舉例
    交集:intersect ,&
    差集: diff ,&~
    子集:subsetOf
    最大:max
    最小:min
    轉成數組,toList
    轉成字符串:mkString(“~”)

Map KV鍵值對集合

  1. map創建
    Map(1 –>”bjsxt’)
    Map((1,”bjsxt”))
 val map = Map(
      "1" -> "bjsxt",
      2 -> "shsxt",
      (3,"xasxt")
    )

  1. 獲取map的值
    map.get(“1”).get
    map.get(100).getOrElse(“no value”):如果map中沒有對應項,賦值爲getOrElse傳的值。
 //獲取值
    println(map.get("1").get)
    val result = map.get(8).getOrElse("no value")
    println(result)

  1. 遍歷map
 //map遍歷    for,foreach
    for(x <- map){
      println("====key:"+x._1+",value:"+x._2)
    }
    
 map.foreach(f => {
      println("key:"+ f._1+" ,value:"+f._2)
    })

  1. 遍歷key
//遍歷key   map.keys
    val keyIterable = map.keys
    keyIterable.foreach { key => {
      println("key:"+key+", value:"+map.get(key).get)
    } }
    println("---------")

  1. 遍歷value
  //遍歷value   map.values
    val valueIterable = map.values
    valueIterable.foreach { value => {
      println("value: "+ value)
    } }
    
  1. 合併map
    ++ 例:map1.++(map2) --map1中加入map2
    ++: 例:map1.++:(map2) –map2中加入map1
    注意:合併map會將map中的相同key的value替換
 //合併map
    val map1 = Map(
      (1,"a"),    
      (2,"b"),    
      (3,"c")    
    )
    val map2 = Map(
      (1,"aa"),
      (2,"bb"),
      (2,90),
      (4,22),
      (4,"dd")
    )
    map1.++:(map2).foreach(println)

  1. map中的方法舉例
  • filter:過濾,留下符合條件的記錄
  • count:統計符合條件的記錄數
  • contains:map中是否包含某個key
  • exist:符合條件的記錄存在不存在
 /**
     * map方法
     */
    //count
    val countResult  = map.count(p => {
      p._2.equals("shsxt")
    })
    println(countResult)
    
    //filter
    map.filter(_._2.equals("shsxt")).foreach(println)
    
    //contains
    println(map.contains(2))
   
    //exist
    println(map.exists(f =>{
      f._2.equals("Angelababy")
      
    }))

元組

1. 元組定義

與列表一樣,與列表不同的是元組可以包含不同類型的元素。元組的值是通過將單個的值包含在圓括號中構成的。

2. 創建元組與取值

  • val tuple = new Tuple(1) 可以使用new
  • val tuple2 = Tuple(1,2) 可以不使用new,也可以直接寫成val tuple3 =(1,2,3)
  • 取值用”._XX” 可以獲取元組中的值
    注意:tuple最多支持22個參數
  //創建,最多支持22個
    val tuple = new Tuple1(1)
    val tuple2 = Tuple2("zhangsan",2)
    val tuple3 = Tuple3(1,2,3)
    val tuple4 = (1,2,3,4)
    val tuple18 = Tuple18(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18)
    val tuple22 = new Tuple22(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)

    //使用
    println(tuple2._1 + "\t"+tuple2._2)
    val t = Tuple2((1,2),("zhangsan","lisi"))
    println(t._1._2)

3. 元組的遍歷

 //遍歷
    val tupleIterator = tuple22.productIterator
    while(tupleIterator.hasNext){
      println(tupleIterator.next())
    }

4. swap,toString方法

   //翻轉,只針對二元組
    println(tuple2.swap)
    
    //toString
    println(tuple3.toString())

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)
    
  }
}

模式匹配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類型的,它將幫你實現setter和getter方法。

  • 樣例類默認幫你實現了toString,equals,copy和hashCode等方法。
  • 樣例類可以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之間傳遞時,自己決定決定去檢查消息,而不是一直等待,是異步非阻塞的
    什麼是Akka
    Akka 是一個用 Scala 編寫的庫,用於簡化編寫容錯的、高可伸縮性的 Java 和Scala 的 Actor 模型應用,底層實現就是Actor,Akka是一個開發庫和運行環境,可以用於構建高併發、分佈式、可容錯、事件驅動的基於JVM的應用。使構建高併發的分佈式應用更加容易。
    spark1.6版本之前,spark分佈式節點之間的消息傳遞使用的就是Akka,底層也就是actor實現的。1.6之後使用的netty傳輸。

2. 例: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 !"

  }
}

3. 例:Actor與Actor之間通信

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()
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章