天天看點

Spark之scala

一、什麼是scala

scala 是基于JVMde 程式設計語言。JAVA是運作在jvm上的程式設計語言,java 源代碼通過jvm被編譯成class 檔案,然後在os上運作class 檔案。scala是運作在jvm 上的程式設計語言,scala源代碼通過jvm被編譯成class檔案,然後在os上運作class檔案。

二文法:

1.聲明值和變量

var a =12 // 定義變量 vary
val  b = 23//  定義常量:value

2.有趣的文法特性

在scala的變量聲明時,可以不指定類型,由解釋器自己判斷。

    “superman ”*3    //表示字元串“ superman”反複輸出3次

    “superman ”*3    //實際上是字元串“ superman”調用方法*,傳入的參數是3

3.函數:

函數在聲明後,無論是否有“=”,都有傳回值。當沒有“=”的時候,表示傳回值是Unit類型,Unit類型的值是()。當有“=”的時候,傳回值是函數體中的最後一行的值。如果傳回值類型強制指定為Unit類型,那麼傳回值必定是()。

4. 判斷:

/**
 * 判斷if
 */
object Test21 extends App{
    def judge(a:Int) :Int = {
      if(a > 0){
         1    //return相當于函數版的break語句
      }else if(a < 0){
        -1
      }else{
        0
      }
    }
    
    var c = judge(-3)
    println(c)
}      
5.循環      
/**
 * while 和 for循環
 */
object Test22 extends App{
    /*while循環*/
//  while(true){
//    println("hello")
//  }
  
  
  /*for循環  scala中的for基本形态*/
//  for(int i = 0 ; i < 5 ; i++)  //java的for循環
//  for( i : List)                  //增強for
  
//  println(1 to 10)   //Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
//  for(i <- 1 to 10 ){  //閉區間
//    println(i)
//  }
  
//  for(i <- 1 until 10 ){  //開區間
//    println(i)
//  }
  
//   for(i <- 1 until 10 reverse){  //倒序  不能使用 10 to 1
//       println(i)
//   }
   
  /*進階for循環*/
  //守衛
//    for(i <- 1 to 10 reverse ; if i % 3 == 0){
//      println(i)
//    }
  
//      for(i <- 1 to (10,3)){   //改變步長
//      println(i)
//    }
  
//  for(i <- 1 to 10 ; j <- 1 to 5){  //雙重for循環
//      println(i + " - " + j)
//  }
  
//  //for的推導式
//  var c = for( i <- 1 to 10 )yield (i * 2)
//  println(c)      

6.常用的資料結構

6.1數組

/**
 * 數組
 */
object Test31 extends App{
  /*定長數組*/
  //使用new定義數組
//    var arr1 = new Array[Int](5)
//    arr1(1) = 2
////    println(arr1)
//    for(i <- arr1){
//      println(i)
//    }
  
  //使用Array類進行定義
  var arr2 = Array(1,2,3,4,"hehe")
//  for( i <- arr2){
//    println(i)
//  }
  
//  println(arr2.min)
//  println(arr2.max)
//  println(arr2.sum)
//  println(arr2.mkString("[",",","]"))   //Arrays.toString(arr)  [1,2,3]
  
  /*變長數組*/
//  var arrbuf1 = ArrayBuffer(1,2,3,4)
//  arrbuf1 += 5
//  arrbuf1 -= 3
//  arrbuf1 ++= Array(3,4,5)
//  arrbuf1 --= Array(3,4,5)
//  arrbuf1.toArray
//  println(arrbuf1.mkString(","))
  
//  var arrB = arr2.toBuffer
//  arrB += 9
//  println(arrB.mkString(","))
  
  
  //filter 和 map用法
  var arr4 = Array(1,2,3,4,5)
  var arr5 = arr4.filter( _ % 2 == 0 ).map( _ * 2)
  println(arr5.mkString(","))
}      
6.2映射      
**
 * 映射
 */
object Test32 extends App{
  /*不可變的映射*/
  //(zhangsan,18)鍵值對稱作對偶   用()表示
    var map1 = Map[String,Int](("zhangsan" , 18) ,( "lisi" , 19))
    map1 += ("wangwu" -> 80)
//    map1("zhangsan") = 12
    map1 += ("zhangsan" -> 20)
//    println(map1("zhangsan"))
//    for(i <- map1){
//      println(i)
//    }
    
//    if(map1.contains("zhaoliu"))
//    println(map1("zhaoliu"))
    
    
    /*可變的映射*/
//    var mapB = scala.collection.mutable.Map[String,Int]("zhangsan"->20,"lisi"->12)
//    mapB("zhangsan") = 30
//    for(i <- mapB){
//      println(i)
//    }
    
    
    /*與java的互操作*/
//    var list = new ArrayList[Int]
//    list.add(1)
//    list.add(2)
//    
//    for(i <- 0 to list.size() - 1 ){
//      println(list.get(i))
//    }
    
    /*map其他周遊方式*/
    
//    for((k,v) <- map1){  //方式一
//      println(k + "->" + v)
//    }
    
    //方式二
    var set1 = map1.keys 
    var set2 = map1.keySet 
    for(i <- set1){
      println(map1(i))
    }
//    println(set2)      
6.3元祖      
/**
 * 元組
 */
object Test33 extends App{
  
  //元組定義
  //對偶(使用“()”表示)隻是元組最簡單的形式  使用()表示
    var t = (1,2,3,4)
//    for(i <- t){   //元組不能使用for周遊
//      println(i)
//    }
    
//    println(t _3)   //元組的下标從1開始
//    println(t _1)   //元組的下标從1開始
    
    var (first,second,third,forth) = t
//    var (first,second,third,_) = t
//    println(second)
    
    var s = "Hello World!"
//    println(s.partition(_.isUpper))
    
    
    //拉鍊操作
    var arr1 = Array(1,2,3,4,5,6)
    var arr2 = Array("a","b","c","d","e")
    var arr3 = arr1.zip(arr2)   //
//    for(i <- arr3){
//      println(i)
//    }
    println(arr3.mkString(","))
    var map = arr3.toMap   //map
    for(i <- map){
      println(i)
    }
          

7.類

類的定義 :使用class定義

類的字段:在類中使用var,val定義字段

類的方法:scala中,使用var定義字段預設提供setter和geter方法,對應的名稱為value_= 和value.

/**
 * 類的基本内容
 */

class TestClass41{
//   @BeanProperty var monary = 100
  var monary = 100
   
//   def show {
//     println("hello")
//   }
}


object Test41 extends App{
  
    var a = new TestClass41()  //執行個體化一個類
    a.monary = 200
    println(a.monary)
//    println(a.show)
    
    //scala使用var定義字段 預設生成對應的setter和getter方法  對應的名稱monary_= 和 monary
    
//    a setMonary 300
//    println(a getMonary)
    
    //使用val定義字段的時候  scala不在提供setter方法
    
    //@BeanProperty和private不能同時共用
    
    
}      
/**
 * 類的基本内容2
 */
class TestClass42{
  private var monary = 0
  
  def setMonary(a:Int){  //自定義setter方法
    if(a > 0)
    this.monary = a
  }
  
  def getMonary = {  //自定義getter方法
    this.monary
  }
  
}

object Test42 extends App{
    var c = new TestClass42
    c setMonary -1000
    println(c getMonary)
    
}      
構造器:      
/**
 * 類的構造器
 */
//class TestClass43(var name:String = "xxx" , var age:Int = 0) {  //主構造器  帶參數稱為預設值
//  
////  var name:String       //需要初始化
////  var age:Int 
////  public TestClass43 {}   //java的構造器寫法
//  println("name=" + name)
//  println("age=" + age)
//  
//}

class TestClass43 {  //輔助構造器 
  var name:String = "lisi"      //需要初始化
  var age:Int = 0
  
  def this(name:String ){
    this()        //輔助構造器第一行要調用主構造器
    this.name = name
    println("第一個輔助構造器")
  }
  
  def this(name:String ,age:Int){
    this(name)    //還可以調用其他輔助構造器
    this.name = name
    this.age = age
    println("第二個輔助構造器")
  }
   
  println("name=" + name + " age=" + age)
  
  def show = {
    "name!=" + name + " age!=" + age
  }
}


object Test43 extends App{
    var c = new TestClass43("wangwu",90)
//    println("name=" + c.name)
//    println("age=" + c.age)
    
    println(c.show)
    
    
}      
8.對象      
定義:Object是一種類型,與class非常相似。      
Object可以提供java中的靜态字段、靜态方法的功能。      
伴生對象      
/**
 * 伴生對象
 */

class TestObject51 {
  private var value = 10
  def display{
    println(TestObject51.value)
  }
  
  def show(a:TestObject51){  //自定義getter方法
    this.value =  TestObject51.value
  }
}

/*伴生對象*/
object TestObject51{    //對象使用object定義
  //該對象作為同名類的伴生對象
//  private[this] var value = 10
  private var value = 10
  
  private def show {
    println("超人")
  }
}

object Test51 extends App{
  
//    println(TestObject51.value)  //不能通路對象中的私有字段
//    println(TestObject51.show)
    
}      
apply 方法:      
f(arg1,arg2,**)是函數調用方法,用着非常好用,如果f是類的執行個體,相當于調用類的apply()方法。      
/**
 * apply方法
 */

object Test52 extends App{
//    var arr = new Array[Int](5)
    var arr = Array.apply(1,2,3,4)  //構造數組使用的是apply方法
    
    var map = Map.apply[String,Int]("zhangsan"->12)
    
}      
9.高階函數      
1.函數可以賦給變量值      
首先,在scala中,函數是一等公民      
2.匿名函數:      
函數的形式是(形參清單)=>傳回值類型      
var ff = (s: string) => s.toUpperCase      
println(ff)      
/**
 * 高階函數
 */

object Test61 extends App{
    //函數定義
    def add(a:Int ,b:Int) = {
      a + b
    }
//    var c = add(1,2)
//    println(c)
    
    var func1 = add _     //把一個函數的實作傳遞給另外一個函數 
//    println(func1(1,2))
    
//    var func2 = (x :Int) =>  x + 3 //傳遞一個匿名函數給給一個變量
//    var func3 = (x :Int) =>  {x + 3} //傳遞一個匿名函數給給一個變量
//    var func4 = (x :Int) =>  (x + 3) //傳遞一個匿名函數給給一個變量
    
//    for(i <- arr)  
//    Map[String,Int]("zhangsan" -> 12)
//    println(func2(3))
    
//    def func5(a:Int ,f:(Int)=>(Int)) = {
//      f(a) + 1
//    }
//    println(func5(4,(x:Int) => {x + 2}))   //傳遞一個匿名函數給該函數
    
    //調用函數封裝舉例
//    def CPU(a:Int) = {
//      a * 8
//    }
//    def GPU(a:Int) = {
//      a + 9
//    }
//    def compute(men:Int,CPU:(Int)=>(Int),GPU:(Int)=>(Int)) = {
//      men + CPU(2) + GPU(2) 
//    }
//    println(compute(4,CPU,GPU))
    
    def func6(f:(Int)=>(Int)) = {
      f(1)
    }
//    println(func6(_ + 2))  //簡寫條件:1.隻有一行代碼   2.隻有一個形參  3.把匿名函數作為形參
//    println(func6(_ + _))  
    
    //總結“_”  :
//    1.代表數組每一個元素
//    2.指的是傳遞是确切的一個函數 而不是忘記給該函數傳遞參數
//    3.元組的元素取值    
    
    //思考題
//    def func7 (x :Int ,y:Int) = {
//      (y : Int) => {
//          x + y
//        } + 2
//    }
//    println(func7(3,4)(2))
    
    //一些有用的函數 map foreach reduceLeft 
//    (1 to 9).map("*" * _).foreach(println _)
    
    var c = (1 to 3).reduceLeft(_ + _)   //1 + 2 + 3
    println(c) 
    
}      
3. 函數作為形參(demo 同上)      

對于隻有一個參數的,可以隻寫函數體。

fun3(a=>a+2)

如果形參隻有一個,可以在函數體中使用_代替。

fun3(_+2)

函數作為形參的終極版本。

4.把匿名函數放在函數體内      
5.一些有用的高階函數      
10.繼承:      

抽象類

    1.抽象類不一定有抽象字段,有抽象字段或者抽象方法的類一定是抽象類,隻需要添加abstract關鍵字

    2.有抽象字段一定是是抽象類(scala中字段定義時一定要初始化)

    3.重寫字段時實質就是在重寫字段的setter/getter方法

覆寫方法

    非抽象類覆寫方法的時候,一定使用override。

覆寫字段

      抽象字段一定要有類型描述。

      覆寫的時候,一定使用override。

/**
 * 繼承--抽象類
 */

abstract class Person {
  //抽象類不一定有抽象字段或者抽象方法
  //有抽象字段或者抽象方法的類  一定是抽象類
  var name:String  
  val age:Int
  def story:String
}

//方式一
//class Student extends Person{  //覆寫字段時實質上是覆寫了字段setter、getter方法
//  var name:String = "Jeckson"  //var定義的字段隻能使用var覆寫,并且var覆寫隻能是為實作的字段 
//  val age:Int = 20        //使用val定義的字段隻能使用val覆寫 
////  def story = "dance"     //
//  def story = "dance"     //使用def定義的抽象方法可以使用def覆寫也可以使用val ,當def為無參時函數可以使用val
//}

//方式二
//class Student (var name:String = "Jeckson" ,val age:Int = 20 ,val story:String = "dance") extends Person 


object Test71 extends App{
//  var c = new Student
//  println(c.name)
//  println(c.age)
//  println(c.story)
  
  var c = new Person {  //方式三  匿名子類
      var name:String = "Jeckson"  //var定義的字段隻能使用var覆寫,并且var覆寫隻能是為實作的字段 
      val age:Int = 20        //使用val定義的字段隻能使用val覆寫 
      def story = "dance"     //
  }
}      

匿名子類重寫超類

Spark之scala
抽象字段和抽象方法
Spark之scala
/**
 * 構造順序
 */
class Person1 {
  val age:Int = 10
  var arr:Array[Int] = new Array[Int](age)  //調age字段的getter方法
}

//class student1 extends Person1{
//  override lazy val age:Int = 18   //如果覆寫的父類不是抽象類  必須要寫override
//}

class student1 extends { //解決辦法③
  override val age:Int = 18   //如果覆寫的父類不是抽象類  必須要寫override
} with Person1

//特質
/*trait student2 {
  var a:Int = 10
  var b:Int
}
trait student3{
  def show = "123"
}
class student4 extends student2 with student3{
  var b:Int = 1
}*/

object Test72 extends App{
    var c = new student1
    println(c.age)
    println(c.arr.length)  
    //輸出18 0   解決辦法:1.字段前面添加final  2.字段前面添加lazy  3.解決辦法③
    //原因:
//      a.主構造器和class類交織在一起
//      b.子類中使用了override覆寫超類中的字段,構造子類時超類的字段值會被覆寫
//      c.student1類作為student1的主構造器,調用了超類的Person1的主構造器
//      d.首先,構造器将age值設定為10
//      e.接着代碼往下走,為了初始化arr數組,調用了age的getter方法
//      f.而age字段被重寫了,也就是說getter方法被重寫了
//      g.被重寫的getter方法還沒有被初始化,确切說就是字段age還是對象在被配置設定空間時所有整型字段的初始值
//      h.arr數組長度被設定為0
//      i.子類Student1類構造器執行,age被指派為18
}      

10 .模式比對

更好的switch case
Spark之scala
object Test73 extends App{
//    var t = (1,2,3)
//    var (first,second,third) = t   //模式比對
//    println(first)
    
    var s = "++"
      
    var result = s match {
      case "a" => println("超人")
      case "*" =>  1
      case "牛人" => "superman"
      case _ if s.contains("=") => (x:Int) => {x + 1} 
      case _ => 0
    }
    
    println(result)
}      

歲月裡,寒暑交替。人世間,北來南往。銘心的,雲煙的。都付往事,不念,不問。

繼續閱讀