1. 程式人生 > >大資料學習筆記(scala)

大資料學習筆記(scala)

1、Scala六大特性

java和scala可以無縫混編(都是基於JVM) 型別推測(不必指定型別,自動推測型別) 支援併發和分散式(Actor) 特質:trait(集結了java中抽象類和介面的產物) 模式匹配(match case :類似於java中的switch case) 高階函式(引數時函式或者返回值是引數)

2、Scala的安裝使用

本教程介紹在Windows下安裝Scala2.10版本。安裝包可以去官網下載。Scala官網。 下載完成之後,解壓在電腦合適位置(記住該位置)。然後配置環境變數(和java配置環境變數一樣) 新建一個系統變數SCALA_HOME,值是Scala安裝包的位置。

編輯Path環境變數,新增;%SCALA_HOME%\bin;%SCALA_HOME%\jre\bin

此時scala安裝完畢,使用win+r輸入cmd開啟命令列,然後輸入scala -version可以看到安裝的scala的版本號。測試成功。

3、Scala基礎

 1)、資料型別
     Byte 		8bite的有符號數字,範圍在-128 – 127
     Short 		16bite的有符號數字,範圍值在-32868 – 32767
     Int 			32bite的有符號數字,範圍在-21億 – 21億
     Long 		64bite的有符號數字,範圍在 負的2的16次方 – 2的16次方
     Float 		32bite 單精度浮點數
     Double 	64bite 雙精度浮點數
     Char 		16bite Unicode字元
     String 		字串
     Boolean 布林型別
     Unit 		表示無值,和其他語言的void相同
     Null 		空值或者空引用
     Nothing 所有其他型別的子型別,表示沒有值
     Any 		所有型別的超類,任何例項都屬於Any型別。類似於java的Object
     AnyRef	所有引用型別的超類
     AnyVal	所有值型別的超類
     Nil			長度為0的List

在這裡插入圖片描述

2)、變數和常量的宣告

    定義變數或者常量的時候,可以寫上返回型別,也可以不寫,如下:
    變數:var age:Int = 20或者var age2 = 18
    常量:val age:Int = 20或者val age2 = 18(常量不可以再次賦值)

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

注意:建議類名首字母大寫 ,方法首字母小寫,類和方法命名建議符合駝峰命名法。 scala 中的object是單例物件,相當於java中的工具類,可以看成是定義靜態的方法的類。object不可以傳引數。另:Trait不可以傳引數 scala中的class類預設可以傳引數,預設的傳引數就是預設的建構函式。 重寫建構函式的時候,必須要呼叫預設的建構函式。 class 類屬性自帶getter ,setter方法。 使用object時,不用new,使用class時要new ,並且new的時候,class中除了方法不執行,其他都執行。

4)、if else

Scala中的if else與java中的用法基本一樣。樣例程式碼如下:

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

講解Scala的迴圈之前,先講解Scala的一個特性:until和to(主要區別是:until前閉後開,to前閉後閉)

   println(1 until 10 )       //不包含最後一個數,列印 1,2,3,4,5,6,7,8,9
   println(1 until (10 ,3 ))  //步長為3,從1開始列印,列印1,4,7
   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

在邏輯上,Scala中的迴圈跟java中的迴圈一樣,只是使用的方式有些區別,下面分別做介紹。 for迴圈

//例子: 列印九九乘法表;相當於java中的雙層for迴圈
    for(i <- 1 until 10 ;j <- 1 until 10){
      if(i>=j){
    	  print(i +" * " + j + " = "+ i*j+"	") 
      }
      if(i==j ){
          println()
      }
    }

與java中不一樣的是,for裡面可以加判斷,如下:

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

while與dowhile跟java中判斷邏輯一樣,下面貼個簡單的while例子:

var index = 0 
    while(index < 100 ){
    	println("第"+index+"次while 迴圈")
        index += 1 
    }

注意點:scala中不能使用count++,count—只能使用count = count+1 ,count += 1 for迴圈用yield 關鍵字返回一個集合val list = for(i <- 1 to 10 ; if(i > 5 )) yield i for迴圈中可以加條件判斷,分號隔開

4、Scala函式

1)、普通函式

函式格式:

def 函式名(變數名:變數型別,...):返回值型別 = {
	   函式體
   }

簡單函式樣例:

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

下面是Scala函式的一些規則和注意點:

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

2)、遞迴函式

遞迴函式就是迴圈呼叫自己,下面給出一個求階乘的程式碼:

def fun2(num :Int) :Int= {
      if(num ==1)
        num
      else 
        num * fun2(num-1)
   }

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宣告的值,匿名函式不能顯式的宣告返回值)

//有引數匿名函式
    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,以上變化的是第二個引數,可以用偏應用函式處理
    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))

5、Scala字串

Scala中字串String仍是不可變數。StringBuild為可變字串。具體操作與java類似。

6、Scala集合

1)、陣列

建立陣列:

//建立型別為Int 長度為3的陣列
    val arr1 = new Array[Int](3)
    //建立String 型別的陣列,直接賦值
    val arr2 = Array[String]("s100","s200","s300")
    //賦值
    arr1(0) = 100
    arr1(1) = 200
    arr1(2) = 300

遍歷陣列:

 for(i <- arr1){
        println(i)
    }
    arr1.foreach(i => {
        println(i)
    })

建立二維陣列:

val secArray = new Array[Array[String]](5)
for(index <- 0 until secArray.length) secArray(index) = new Array[String](3)

2)、list

list是不可變的,對list進行新增刪除或者取值等操作均會返回一個新的list。

   val list = List(1,3,5,9)
   println(list.contains(9))
   val dropList = list.drop(2)
   dropList.foreach { println }
   val reList = list.reverse
   reList.foreach { x => print(x + "\t") }

3)、set

set是一個非重複的集合,若有重複資料,則會自動去重。

   val set = Set(1,3,5,8,1,6,5,8)
   set.foreach { x => print(x + "\t") }

4)、map

map是K-V鍵值對集合。

//建立map
   val map = Map(
       "1" -> "bj" ,
       2 -> "sh",
       3 -> "gz"
    )
    
    //map遍歷
    for(x <- map){
       println("====key:"+x._1+",value:"+x._2)
    }
    
    //遍歷key
    var keys = map.keys
    //獲取key的迭代器
    var keyIterator = keys.iterator
    while(keyIterator.hasNext){
       val key = keyIterator.next()
       println(key + "\t" + map.get(key).get)
    }

5)、元組

與列表一樣,與列表不同的是元組可以包含不同型別的元素。元組的值是通過將單個的值包含在圓括號中構成的。建立過程可加new關鍵詞,也可不加。

//建立二元組,下面兩句話效果相同
    val t2 = new Tuple2(1,"hello")
    val tt2 = (1,"hello")
    
    //建立三元組,下面兩句話效果相同
    val t3 = Tuple3(2,"bj","come")
    val tt3 = (2,"bj","come")
    
    //建立tt3的迭代器
    val tupleIte = tt3.productIterator
    while(tupleIte.hasNext) print(tupleIte.next + "\t")
    
    //反轉,只針對二元組
    val swap = tt2.swap
    
    //toString
    println(tt3.toString())

7、Scala trait特性

Scala Trait(特徵)相當於java中抽象類和介面的集合體,不只是具備介面的特徵,還可以定義屬性和方法的實現。一般情況下Scala的類可以繼承多個Trait,從結果來看就是實現了多重繼承。Trait(特徵) 定義的方式與類類似,但它使用的關鍵字是 trait。 繼承的多個trait中如果有同名的方法和屬性,必須要在類中使用“override”重新定義。並且trait中不可以傳引數。

//定義一個trait
trait Read {
  val readType = "Read"
  val gender = "m"
  def read(name:String){
	println(name+" is reading")
  }
}

//定義第二個trait
trait Listen {
  val listenType = "Listen"
  val gender = "m"
  def listen(name:String){
	println(name + " is listenning")
  }
}

//定義了一個類繼承上面兩個trait
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)
    
  }
}

8、Scala 模式匹配

模式匹配類似於java的switch case。Scala的模式匹配不僅可以匹配值還可以匹配型別、從上到下順序匹配,如果匹配到則不再往下匹配、都匹配不上時,會匹配到case _ ,相當於default、match 的最外面的”{ }”可以去掉看成一個語句。

def match_test(m:Any) = {
       m match {
         case 1 => println("nihao")
         case m:Int => println("Int")
         case _ => println("default")
       }
    }

9、Scala 樣例類

使用了case關鍵字的類定義就是樣例類(case classes),樣例類是種特殊的類。實現了類構造引數的getter方法(構造引數預設被宣告為val),當構造引數是宣告為var型別的,它將幫你實現setter和getter方法。 樣例類預設幫你實現了toString,equals,copy和hashCode等方法。 樣例類可以new, 也可以不用new。

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

object Lesson_CaseClass {
   def main(args: Array[String]): Unit = {
      val p = new Person1("zhangsan",10)
  }
}

10、Scala Actor

Actor Model是用來編寫平行計算或分散式系統的高層次抽象(類似java中的Thread)讓程式設計師不必為多執行緒模式下共享鎖而煩惱,每個Actors有自己的世界觀,當需要和其他Actors互動時,通過傳送事件和訊息,傳送是非同步的,非堵塞的(fire-andforget),傳送訊息後不必等另外Actors回覆,也不必暫停,每個Actors有自己的訊息佇列,進來的訊息按先來後到排列,這就有很好的併發策略和可伸縮性,可以建立效能很好的事件驅動系統。 Actor的特徵: ActorModel是訊息傳遞模型,基本特徵就是訊息傳遞 訊息傳送是非同步的,非阻塞的 訊息一旦傳送成功,不能修改 Actor之間傳遞時,自己去檢查訊息,而不是一直等待,是非同步非阻塞的

object Scala07 {
  def main(args: Array[String]): Unit = {
    val actor = new MyActor
    actor.start()
    actor ! "hello bj"
  }
}

class MyActor extends Actor{
  def act() = {
    while(true){
      receive{
        case s: String => println(s)
        case _ =>println("default")
      }
    }
  }
}