Scala——多範式, 可伸縮, 類似Java的編程語言

第一章 是什麼

一 Scala 介紹

Scala是一門多範式, 類似java的編程語言 ,設計初衷是實現可伸縮的語言、並集成面向對象編程和函數式編程的各種特性
Scala以一種簡潔、高級的語言將面向對象和函數式編程結合在一起.Scala的靜態類型有助於避免複雜應用程序中的bug,它的JVM和JavaScript運行時允許構建高性能的系統,可以輕鬆地訪問龐大的庫生態系統。
Spark1.6中使用的是Scala2.10。Spark2.0版本以上使用是Scala2.11版本。
官方網址 https://www.scala-lang.org/

Scala六大特性

  1. 無縫整合JAVA
    Scala在JVM上運行,因此Java和Scala堆棧可以自由混合,以實現完全無縫集成. 可以相互調用對方的包, 甚至是混編。

  2. 類型自動推斷
    自動推測識別變量的類型, 類似Python

  3. 併發與分佈式
    actor:節點之間的通信,是一種通信模型
    對集合使用數據並行操作,使用參與者進行併發和分發,或者使用將來進行異步編程。

  4. 特性/特質(類似java中interfaces 和 abstract結合)
    將Java風格接口的靈活性與類的強大功能結合起來。有原則的多重繼承。

  5. 模式匹配
    類似switch語句。與類層次結構、序列等進行匹配。

  6. 高階函數
    一切皆函數, 函數就是方法
    函數是第一級的對象.用保證型安全的方式組成它們。在任何地方使用它們,把它們傳給任何事物


第二章 Scala 安裝使用

一 安裝語言環境

  1. windows安裝(運行scala-2.11.2.msi 自動安裝程序), 配置環境變量
    官網下載scala2.10:http://www.scala-lang.org/download/2.10.4.html
    下載好後安裝(分享至末尾)。
    雙擊msi包安裝, 記住安裝的路徑。
    配置環境變量(和配置jdk一樣)
    新建SCALA_HOME, 指定Scala安裝目錄; 在配置環境變量Path: %SCALA_HOME%\bin
    在這裏插入圖片描述
  2. 通過cmd測試是否安裝成功
    在這裏插入圖片描述

二 常用開發工具整合Scala插件

目的是使當前開發工具能夠支持Scala的開發

  • 方式一 eclipse 配置scala插件
    1. 下載插件(一定要對應eclipse版本下載)
    http://scala-ide.org/download/prev-stable.html
    2. 下載好zip包後,解壓如下:
    在這裏插入圖片描述
    3.將features和plugins兩個文件夾拷貝到eclipse安裝目錄中的” dropins/scala”目錄下。進入dropins,新建scala文件夾,將兩個文件夾拷貝到“dropins/scala”下

  • 方式二 scala ide
    下載Scala官方整合的eclipse軟件開發工具集, 下載打開即可使用
    下載網址:http://scala-ide.org/download/sdk.html

  • 方式三 idea 中配置scala插件
    打開idea,close項目後,點擊Configure->Plugins->輸入Scala下載插件
    或者通過打開 File->Settings->Plugins->輸入Scala下載插件(圖1)

    圖1
    在這裏插入圖片描述

三 創建Scala項目

使用IDEA編寫Scala代碼, 更符合現在公司趨勢

  1. 在我們整合Scala以後, 再次創建新的項目就會有Scala選項
    在這裏插入圖片描述
  2. 指定項目相關信息
    jdk必須爲1.8這個大版本
    需要指定Scala SDK,這裏一開始時沒有的,需要我們手動創建, 目錄就是我們的Scala的語言環境安裝地址
    在這裏插入圖片描述
    出現這個並選中才是成功配置了Scala開發環境
    在這裏插入圖片描述
    創建項目成功以後最好是自己配置一下Maven倉庫, 指定阿里巴巴鏡像倉庫, 這樣下載jar資源速度更快
    在這裏插入圖片描述
    如果以上環境都配置完成後, 仍無法 new Scala Class, 請看這裏
    在這裏插入圖片描述

第三章 Scala 基礎

一 數據類型

在這裏插入圖片描述

新增類型的繼承關係
在這裏插入圖片描述
部分新增類型的解釋
在這裏插入圖片描述

二 變量常量聲明

定義變量或者常量的時候,也可以寫上返回的類型,一般省略,如:val a:Int = 10
常量不可再賦值

/**
     * 定義變量和常量
     * 變量 :用 var 定義 ,可修改 
     * 常量 :用 val 定義,不可修改
     */
    var name = "TP"
    println(name)
    name ="lisi"
    println(name)
    val gender = "m"
//    gender = "m"//錯誤,不能給常量再賦值

三 類和對象使用

  1. 創建類

    class Person{
      val name = "TP"
      val age = 18
      def sayName() = {
        "my name is "+ name
      }
    }
    
  2. 創建對象

    object Lesson_Class {
       def main(args: Array[String]): Unit = {
        val person = new Person()
        println(person.age);
        println(person.sayName())
      }
    }
    
  3. 對象中的apply方法
    object中不可以傳參,當創建一個object時,如果傳入參數,那麼會自動尋找object中的相應參數個數的apply方法。

    /**
      * object 單例對象中不可以傳參,
      * 如果在創建Object時傳入參數,那麼會自動根據參數的個數去Object中尋找相應的apply方法
      */
    object Lesson_ObjectWithParam {
      def apply(s:String) = {
        println("name is "+s)
      }
      def apply(s:String,age:Int) = {
        println("name is "+s+",age = "+age)
      }
      def main(args: Array[String]): Unit = {
        Lesson_ObjectWithParam("TP")
        Lesson_ObjectWithParam("lisi",18)
      }
    }
    
    
  4. 伴生類和伴生對象

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

注意:

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

個人學習code

/**
 * 1.Scala中定義常量使用val ,常量不可變,定義變量使用var,變量可變。定義變量和常量時會有類型自動推斷機制,可以顯式寫出變量和常量的類型,一般省略
 * 2.Scala中每行有自動的分號推斷機制,不需要在每行後寫“;* 3.Scala中有classobject,定義class時可以傳參,但是參數一定要指定參數類型,給類傳參就有默認的構造。
 *   重寫構造時,第一行必須先調用默認的構造。
 * 4.Scala中的object相當於java中的單例,類似於Java中的工具類,Object中定義的所有屬性和方法都是靜態的,調用時直接使用對象名.屬性|方法。
 *   Object不可以傳參,Trait也不可以傳參。
 *
 * 5.在一個Scala文件中,如果class的名稱和Object的名稱一致,這個class叫做這個object的伴生類,這個object叫做這個class伴生對象,他們之間可以訪問私有變量。
 *
 * Create by TimePause
 * Create on 2019/12/10
 */
class Person{
  // 在定義成私有變量後, 如果還想讓object獲取類的屬性, 只需要將二者的名稱設置成一樣即可
  private var name="TimePause"
  val age="18"

  println("===========================")
}

class Person3(xname:String,xage:Int){
  val name=xname
  val age=xage
  var gender='f'
  def this(yname:String,yage:Int,ygender:Char){
    this(yname,yage)
    this.gender=ygender
  }
  def  showScore(c:String): Unit ={
   // println(s"Class=${c} Score="+ObjetAndClass.score)
  }
}
class Person2(xname:String,xage:Int){
  val name=xname
  val age=xage
}
class Person1{
  val name="TimePause"
  val age="18"
}

object ObjetAndClass {
  // 相當於靜態變量/類變量
  val score=66
  // 使用apply方法實現object值的傳遞
  def apply(s: String, i: Int) = {
    println(s"name=$s age=$i")
  }

  def main(args: Array[String]): Unit = {
    ObjetAndClass("TP",22)

    //println("hello world")
    //儘量使用val, 因爲val類型數據更容易被內存回收
    val person=new Person()
   // println(s"person name= ${person.name}")
    println(s"person age="+ person.age)
   // println(s"person gender="+ person.gender)
   // person.showScore("班級1")
  }
}

四 條件語句

  1. 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")
    }
  1. for ,while,do…while
 	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

  1. for循環
 //可以分號隔開,寫入多個list賦值的變量,構成多層for循環
    //scala中 不能寫count++ count-- 只能寫count+
    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()
      }
      
    }

  1. for循環中可以加條件判斷,可以使用分號隔開,也可以不使用分號

     //可以在for循環中加入條件判斷
        for(i<- 1 to 10 ;if (i%2) == 0 ;if (i == 4) ){
          println(i)
    }
    
  2. scala中不能使用count++,count—只能使用count = count+1 ,count += 1

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

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

個人學習code

object IfAndLoopStatement {
  def main(args: Array[String]): Unit = {
    //for循環
    for (i <- 1 to 10) {
      println(i)
    }
    // 打印110
    println(1 to 10) //Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    println(1.to(10)) //Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    println(1.to(10, 2)) //Range(1, 3, 5, 7, 9)
    // 打印 19(10-1)
    println(1 until 10) //Range(1, 2, 3, 4, 5, 6, 7, 8, 9)
  }

  /**
   * 九九乘法表瞭解一下1
   */
/*  for (i <- 1.to(9)) {
    for (j <- 1.until(10)) {
      if (i >= j) {
        print(s"$i * $j= ${i * j}\t")
      }
      if (i == j) {
        println()
      }
    }
  }*/

  /**
   * 九九乘法表2
   * 分號並行書寫,自動識別內層循環
   */
  for (i <- 1.to(9) ;j <- 1.until(10)) {
      if (i >= j) {
        print(s"$i * $j= ${i * j}\t")
      }
      if (i == j) {
        println()
      }
  }
  println("-----------------------------------")
  //for..if
  for(i <- 1.to(100) if(i%2==0) if(i>50) ){
    print(i+"\t")
  }
  //if...else, do...while同java一致
  //while循環語句
  var i=1
  while (i<100){
    println(s"第$i 次考六級")
    i+=1   //需要注意的是這裏沒有i++
  }
}


第四章 Scala 的方法與函數

一 函數方法的定義

在這裏插入圖片描述

/**
     * 一 單方法定義
     * 1. 方法定義使用def, 方法的參數必須指定參數類型
     * 2. 方法返回值, 可使用return, 也可以省略return, 但不建議使用, 如果使用必須聲明方法的返回值類型
     * 3. 方法的返回值類型也可以省略, Scala可以自動推斷
     * 4. 如果方法體可以一行搞定, 那麼方法體 {} 可以省略
     * 5. 如果定義方法時等號省略, 那麼方法體中最後一行無論是什麼, 都會被丟棄, 返回Unit/*/
    def max(x: Int, y: Int): Int = {
      if (x > y) {
        x
      }
      else {
        y
      }
    }
	//如果方法體中的語句可以一行寫完,那麼if...else...所在函數可以寫成這樣
    def max2(x: Int, y: Int): Int = if (x > y) x else y
    
    println(max(666, 888))

二 遞歸方法

 /**
     * 二 定義遞歸方法
     * 遞歸方法必須顯示聲明方法的返回值類型
     */
    def recursionFun(num: Int): Int = {
      if (num == 1) {
        1
      } else {
        num * recursionFun(num - 1)
      }
    }
    println(recursionFun(5))

運行結果
在這裏插入圖片描述

三 參數有默認值的方法

   /**
     * 三 參數有默認值的方法
     * 1. 默認值的函數中,如果傳入的參數個數與函數定義相同,則傳入的數值會覆蓋默認值
     * 2. 如果不想覆蓋默認值,傳入的參數個數小於定義的函數的參數,則需要指定參數名稱
     */
    def fun(a: Int = 100, b: Int = 200): Int = {
      a + b
    }
    println(fun(b=100))
  }

運行結果
在這裏插入圖片描述

四 可變參數的方法

/**
   * 四 可邊長參數的方法
   * 注意:多個參數逗號分開
   */
  def fun1(elems: String*): Unit = {
    for (elem <- elems) {
      println(elem)
    }
  }
  fun1("helloword","h","e","l","l","o")
  /**
   * 五 遍歷集合方法/函數
   *
   * @param elems
   */
  def fun2(elems: String*): Unit = {
    //這是最簡過程(只有一個參數可以)
    elems.foreach(println)
    //   elems.foreach(println(_))
    //   elems.foreach(one=>{
    //     println(one)
    //   })
  }

  fun2("helloword","h","e","l","l","o")

運行結果
在這裏插入圖片描述

五 匿名函數

 /**
   * 六 匿名函數
   * 1.有參數匿名函數
   * 2.無參數匿名函數
   * 3.有返回值的匿名函數
   * 注意:
   * "=>"就是匿名函數
   * 如何調用匿名函數? 將匿名函數賦值給一個變量
   * 當方法的參數需要傳遞的參數爲函數時,就可使用匿名函數
   */
  var fun3 = () => {
    println("HelloWorld")
  }
  //fun3()
  val fun4: (Int, Int) => Int = (a: Int, b: Int) => {
    a + b
  }
  //println(fun4(100,222))

運行結果
在這裏插入圖片描述

六 嵌套函數/方法

  /**
   * 七 嵌套方法
   * 利用嵌套實現階乘
   */
  def fun6(a: Int): Int = {
    def fun5(num: Int): Int = {
      if (num == 1) {
        1
      } else {
        num * fun5(num - 1)
      }
    }

    fun5(a)
  }
  println(fun6(5))

運行結果
在這裏插入圖片描述

七 偏應用函數

/**
   * 八 偏應用函數
   * 偏應用函數是一種表達式,不需要提供函數需要的所有參數,只需要提供部分,或不提供所需參數。
   * 從這裏可以看出Scala與java無縫整合的特性,因爲Scala可以掉Java的相關包,例如java.util.Date
   */
  def showlog(d: Date, log: String): Unit = {
    println(s"時間爲: $d, 日誌信息爲: $log")
  }

  var d = new Date()
  showlog(d, "hello")
  showlog(d, "hello")
  showlog(d, "hello")
  // -代表第一個參數是固定值, 我們可以不寫
  var fun7 = showlog(d, _: String);
  fun7("a")
  fun7("b")
  fun7("c")

運行結果

在這裏插入圖片描述

八 高階函數

  /**
   * 九 高階函數
   * 函數的參數是函數,或者函數的返回類型是函數,或者函數的參數和函數的返回類型是函數的函數。
   * 1. 方法的參數是函數( 最重要 )
   * 2. 方法的返回值是函數
   * 3. 方法的參數和返回值都是函數
   */
  //1.方法的參數是函數
  def fun8(a: Int, b: Int): Int = {
    a + b
  }

  def fun9(f: (Int, Int) => Int, s: String) = {
    var r: Int = f(10, 20)
    r + "===" + s
  }
  println(fun9(fun8, "方法的參數中傳入了函數"))
  println(fun9((a:Int,b:Int)=>{a*b},"使用匿名函數讓兩個函數相乘"))

  // 2.方法的返回值是函數
  def fun10(a: Int, b: Int): (String, String) => (String) = {
    var r = a + b

    def fun11(s1: String, s2: String): String = {
      r + "===" + s1 + s2
    }
    //這裏省略了一個return,代表返回一個函數
    fun11
  }
  println(fun10(10, 20)("a", "b"))

  //3. 方法的參數和返回值都是函數
  def fun12(f: (Int, Int) => Int, i: Int): (String, String) => (String) = {
    val r = f(10, 20) + i

    def fun13(s1: String, s2: String): String = {
      r + "===" + s1 + s2
    }
    fun13
  }
  println(fun12((a: Int, b: Int) => {a * b}, 100)("a", "b"))

運行結果
在這裏插入圖片描述

九 科裏化函數

/**
   * 科裏化函數
   * ------高階高數的簡化
   */
  def fun14(a: Int, b: Int)(c: Int, d: Int): Int = {
    a + b + c + d
  }
  println(fun14(1, 2)(3, 4))

運行結果
在這裏插入圖片描述


第五章 集合

零 Scala 字符串

  1. String
  2. StringBuilder 可變
  3. string操作方法舉例
    比較:equals
    比較忽略大小寫:equalsIgnoreCase
    indexOf:如果字符串中有傳入的assci碼對應的值,返回下標
/**
     * String的相關方法用法同Java一致
     */
    val s1="megalo box"
    val s2="MEGALO BOX"
    //判等
    println(s1.equals(s2))
    println(s1.equalsIgnoreCase(s2))
    //返回當前ascall碼對應字符是否出現, 如果出現則返回其下標, 如果出現返回-1
    println(s1.indexOf(66))

    //StringBuilder的實驗
    val sb=new StringBuilder();
    sb.append("you ")
    sb.append("are ")
    sb.append("my darling~~~")
    println(sb.toString())

運行結果
在這裏插入圖片描述

String相關方法總結

char charAt(int index)
返回指定位置的字符  從0開始
	
int compareTo(Object o)
比較字符串與對象
	
int compareTo(String anotherString)
按字典順序比較兩個字符串
	
int compareToIgnoreCase(String str)
按字典順序比較兩個字符串,不考慮大小寫
	
String concat(String str)
將指定字符串連接到此字符串的結尾
	
boolean contentEquals(StringBuffer sb)
將此字符串與指定的 StringBuffer 比較。
	
static String copyValueOf(char[] data)
返回指定數組中表示該字符序列的 String
	
static String copyValueOf(char[] data, int offset, int count)
返回指定數組中表示該字符序列的 String
	
boolean endsWith(String suffix)
測試此字符串是否以指定的後綴結束
	
boolean equals(Object anObject)
將此字符串與指定的對象比較
	
boolean equalsIgnoreCase(String anotherString)
將此 String 與另一個 String 比較,不考慮大小寫
	
byte getBytes()
使用平臺的默認字符集將此 String 編碼爲 byte 序列,並將結果存儲到一個新的 byte 數組中
	
byte[] getBytes(String charsetName
使用指定的字符集將此 String 編碼爲 byte 序列,並將結果存儲到一個新的 byte 數組中
	
void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
將字符從此字符串複製到目標字符數組
	
int hashCode()
返回此字符串的哈希碼
16	
int indexOf(int ch)
返回指定字符在此字符串中第一次出現處的索引(輸入的是ascii碼值)
	
int indexOf(int ch, int fromIndex)
返返回在此字符串中第一次出現指定字符處的索引,從指定的索引開始搜索
	
int indexOf(String str)
返回指定子字符串在此字符串中第一次出現處的索引
	
int indexOf(String str, int fromIndex)
返回指定子字符串在此字符串中第一次出現處的索引,從指定的索引開始
	
String intern()
返回字符串對象的規範化表示形式
	
int lastIndexOf(int ch)
返回指定字符在此字符串中最後一次出現處的索引
	
int lastIndexOf(int ch, int fromIndex)
返回指定字符在此字符串中最後一次出現處的索引,從指定的索引處開始進行反向搜索
	
int lastIndexOf(String str)
返回指定子字符串在此字符串中最右邊出現處的索引
	
int lastIndexOf(String str, int fromIndex)
返回指定子字符串在此字符串中最後一次出現處的索引,從指定的索引開始反向搜索
	
int length()
返回此字符串的長度
	
boolean matches(String regex)
告知此字符串是否匹配給定的正則表達式
	
boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)
測試兩個字符串區域是否相等

boolean regionMatches(int toffset, String other, int ooffset, int len)
測試兩個字符串區域是否相等
	
String replace(char oldChar, char newChar)
返回一個新的字符串,它是通過用 newChar 替換此字符串中出現的所有 oldChar 得到的
	
String replaceAll(String regex, String replacement
使用給定的 replacement 替換此字符串所有匹配給定的正則表達式的子字符串
	
String replaceFirst(String regex, String replacement)
使用給定的 replacement 替換此字符串匹配給定的正則表達式的第一個子字符串
	
String[] split(String regex)
根據給定正則表達式的匹配拆分此字符串
	
String[] split(String regex, int limit)
根據匹配給定的正則表達式來拆分此字符串
	
boolean startsWith(String prefix)
測試此字符串是否以指定的前綴開始
	
boolean startsWith(String prefix, int toffset)
測試此字符串從指定索引開始的子字符串是否以指定前綴開始。
	
CharSequence subSequence(int beginIndex, int endIndex)
返回一個新的字符序列,它是此序列的一個子序列
	
String substring(int beginIndex)
返回一個新的字符串,它是此字符串的一個子字符串
	
String substring(int beginIndex, int endIndex)
返回一個新字符串,它是此字符串的一個子字符串
	
char[] toCharArray()
將此字符串轉換爲一個新的字符數組
	
String toLowerCase()
使用默認語言環境的規則將此 String 中的所有字符都轉換爲小寫
	
String toLowerCase(Locale locale)
使用給定 Locale 的規則將此 String 中的所有字符都轉換爲小寫
	
String toString()
返回此對象本身(它已經是一個字符串!)
	
String toUpperCase()
使用默認語言環境的規則將此 String 中的所有字符都轉換爲大寫
	
String toUpperCase(Locale locale)
使用給定 Locale 的規則將此 String 中的所有字符都轉換爲大寫
	
String trim()
刪除指定字符串的首尾空白符
	
static String valueOf(primitive data type x)
返回指定類型參數的字符串表示形式

一 數組

數組相關方法總結

序號 方法 描述
1 def apply( x: T, xs: T* ): Array[T] 創建指定對象 T 的數組, T 的值可以是 Unit, Double, Float, Long, Int, Char, Short, Byte, Boolean。
2 def concat[T]( xss: Array[T]* ): Array[T] 合併數組
3 def copy( src: AnyRef, srcPos: Int, dest: AnyRef, destPos: Int, length: Int ): Unit 複製一個數組到另一個數組上。相等於 Java’s System.arraycopy(src, srcPos, dest, destPos, length)。
4 def empty[T]: Array[T] 返回長度爲 0 的數組
5 def iterate[T]( start: T, len: Int )( f: (T) => T ): Array[T] 返回指定長度數組,每個數組元素爲指定函數的返回值。以上實例數組初始值爲 0,長度爲 3,計算函數爲a=>a+1:scala> Array.iterate(0,3)(a=>a+1) ; res1: Array[Int] = Array(0, 1, 2)
6 def fill[T]( n: Int )(elem: => T): Array[T] 返回數組,長度爲第一個參數指定,同時每個元素使用第二個參數進行填充。
7 def fill[T]( n1: Int, n2: Int )( elem: => T ): Array[Array[T]] 返回二數組,長度爲第一個參數指定,同時每個元素使用第二個參數進行填充。
8 def ofDim[T]( n1: Int ): Array[T] 創建指定長度的數組
9 def ofDim[T]( n1: Int, n2: Int ): Array[Array[T]] 創建二維數組
10 def ofDim[T]( n1: Int, n2: Int, n3: Int ): Array[Array[Array[T]]] 創建三維數組
11 def range( start: Int, end: Int, step: Int ): Array[Int] 創建指定區間內的數組,step 爲每個元素間的步長
12 def range( start: Int, end: Int ): Array[Int] 創建指定區間內的數組
13 def tabulate[T]( n: Int )(f: (Int)=> T): Array[T] 返回指定長度數組,每個數組元素爲指定函數的返回值,默認從 0 開始。以上實例返回 3 個元素:scala> Array.tabulate(3)(a => a + 5) ; res0: Array[Int] = Array(5, 6, 7)
14 def tabulate[T]( n1: Int, n2: Int )( f: (Int, Int ) => T): Array[Array[T]] 返回指定長度的二維數組,每個數組元素爲指定函數的返回值,默認從 0 開始。
object ArrayStudy {
  def main(args: Array[String]): Unit = {
    val arr=Array[String]("w","z","r","y")
    //遍歷方式1(最簡化)
    arr.foreach(println)
    //遍歷方式2(方式1的正式版)
    arr.foreach(one=>{
      println(one)
    })
    //遍歷方式3( 最容易理解 )
    for (a <-arr){
      println(a)
    }

    println("數組初始化")
    val arr1=new Array[String](3)
    arr1(0)="y"
    arr1(1)="y"
    arr1(2)="s"
    //arr1.foreach(println)

    println("二維數組定義,初始化,遍歷")
    val arr2=new Array[Array[String]](3)
    arr2(0)=Array[String]("y","y","s")
    arr2(1)=Array[String]("c","l","x")
    arr2(2)=Array[String]("c","x","k")
    //遍歷1
    arr2.foreach(elem=> elem.foreach(println))
    //遍歷2
    for (ar<-arr2; elem<-arr){
      println(elem)
    }

    println("創建數組並初始化,演示concat方法")
    //val arr3=Array[Int](6,6,6)
    val arr3=Array[String]("tp","n","sh")
    val arr4=Array[String]("TP","N","SH")
    val arr5:Array[String]=Array.concat(arr3,arr4)
    arr5.foreach(println)
    println("創建數組並初始化,使用fill填充數組")
    val arr6=Array.fill(3)("hello")
    arr6.foreach(println)

    println("創建可邊長字符數組---------------")
    val arrbuf=ArrayBuffer[String]("szxy","wg","tp")
    arrbuf.append("like")
    arrbuf.append("freedom")
    arrbuf.foreach(println)
  }
}

二 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

flatmap的圖解
在這裏插入圖片描述

list相關方法總結

1	def +(elem: A): List[A]
前置一個元素列表
2	def ::(x: A): List[A]
在這個列表的開頭添加的元素。
3	def :::(prefix: List[A]): List[A]
增加了一個給定列表中該列表前面的元素。
4	def ::(x: A): List[A]
增加了一個元素x在列表的開頭
5	def addString(b: StringBuilder): StringBuilder
追加列表的一個字符串生成器的所有元素。
6	def addString(b: StringBuilder, sep: String): StringBuilder
追加列表的使用分隔字符串一個字符串生成器的所有元素。
7	def apply(n: Int): A
選擇通過其在列表中索引的元素
8	def contains(elem: Any): Boolean
測試該列表中是否包含一個給定值作爲元素。
9	def copyToArray(xs: Array[A], start: Int, len: Int): Unit
列表的副本元件陣列。填充給定的數組xs與此列表中最多len個元素,在位置開始。
10	def distinct: List[A]
建立從列表中沒有任何重複的元素的新列表。
11	def drop(n: Int): List[A]
返回除了第n個的所有元素。
12	def dropRight(n: Int): List[A]
返回除了最後的n個的元素
13	def dropWhile(p: (A) => Boolean): List[A]
丟棄滿足謂詞的元素最長前綴。
14	def endsWith[B](that: Seq[B]): Boolean
測試列表是否使用給定序列結束。
15	def equals(that: Any): Boolean
equals方法的任意序列。比較該序列到某些其他對象。
16	def exists(p: (A) => Boolean): Boolean
測試謂詞是否持有一些列表的元素。
17	def filter(p: (A) => Boolean): List[A]
返回列表滿足謂詞的所有元素。
18	def forall(p: (A) => Boolean): Boolean
測試謂詞是否持有該列表中的所有元素。
19	def foreach(f: (A) => Unit): Unit
應用一個函數f以列表的所有元素。
20	def head: A
選擇列表的第一個元素
21	def indexOf(elem: A, from: Int): Int
經過或在某些起始索引查找列表中的一些值第一次出現的索引。
22	def init: List[A]
返回除了最後的所有元素
23	def intersect(that: Seq[A]): List[A]
計算列表和另一序列之間的多重集交集。
24	def isEmpty: Boolean
測試列表是否爲空
25	def iterator: Iterator[A]
創建一個新的迭代器中包含的可迭代對象中的所有元素
26	def last: A
返回最後一個元素
27	def lastIndexOf(elem: A, end: Int): Int
之前或在一個給定的最終指數查找的列表中的一些值最後一次出現的索引
28	def length: Int
返回列表的長度
29	def map[B](f: (A) => B): List[B]
通過應用函數以g這個列表中的所有元素構建一個新的集合
30	def max: A
查找最大的元素
31	def min: A
查找最小元素
32	def mkString: String
顯示列表的字符串中的所有元素
33	def mkString(sep: String): String
顯示的列表中的字符串中使用分隔串的所有元素
34	def reverse: List[A]
返回新列表,在相反的順序元素
35	def sorted[B >: A]: List[A]
根據排序對列表進行排序
36	def startsWith[B](that: Seq[B], offset: Int): Boolean
測試該列表中是否包含給定的索引處的給定的序列
37	def sum: A
概括這個集合的元素
38	def tail: List[A]
返回除了第一的所有元素
39	def take(n: Int): List[A]
返回前n個元素
40	def takeRight(n: Int): List[A]
返回最後n個元素
41	def toArray: Array[A]
列表以一個數組變換
42	def toBuffer[B >: A]: Buffer[B]
列表以一個可變緩衝器轉換
43	def toMap[T, U]: Map[T, U]
此列表的映射轉換
44	def toSeq: Seq[A]
列表的序列轉換
45	def toSet[B >: A]: Set[B]
列表到集合變換
46	def toString(): String
列表轉換爲字符串

個人練習code

/**
 * Author TimePause
 * Create  2019-12-11 10:55
 */
object ListStudy {
  def main(args: Array[String]): Unit = {
    /**
     * 不可變長的list
     */
    println("定義list,遍歷")
    val list=List[String]("ah","sz","xxgcxy")
    println("方式一,常用")
    list.foreach(println)
    println("方式二")
    for (elem <-list){
      println(elem)
    }


    println("-------list中的map方法用於切分數組元素,將每個切分後的元素放入到一個數組中(一對一)-------")
    // list:集合 Array:數組  通過map方法獲得的素組需要我們再次遍歷才能得到元素值
    val list2=List[String]("hi boy","hi girl","hi everyone")
    val listMap:List[Array[String]]=list2.map(one=>{one.split(" ")})
    listMap.foreach(one=>{
      println("==========")
      println(one)
      one.foreach(println)
    })

    println("-------list中的flatmap方法用於切分數組元素,將所有切分後的元素放入到一個數組中(一對多)-------")
    //這樣我們就可以直接遍歷這個對象了
    val strings: List[String] = list2.flatMap(one => {
      one.split(" ")
    })
    strings.foreach(println)

    println("--------filter,過濾作用-------------")
    val strings1: List[String] = list2.filter(one => {
      //one.equals("hi boy")
      !one.equals("hi boy")
    })
    strings1.foreach(println)

   println("--------count,統計元素個數------------")
    val i: Int = list2.count(one => {
      one.equals("hi boy")
    })
    println(i)


    /**
     * 可邊長的list
     */
    println("可邊長字符串測試")
    val listbuf=new ListBuffer[String]()
    listbuf.append("I")
    listbuf.append("am")
    listbuf.append("the flash")
    println(listbuf)
  }


}

三 Set

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

Set相關方法總結

Scala Set 常用方法
下表列出了 Scala Set 常用的方法:
序號	方法 描述
1	
def +(elem: A): Set[A]
爲集合添加新元素,x並創建一個新的集合,除非元素已存在
2	
def -(elem: A): Set[A]
移除集合中的元素,並創建一個新的集合
3	
def contains(elem: A): Boolean
如果元素在集合中存在,返回 true,否則返回 false。
4	
def &(that: Set[A]): Set[A]
返回兩個集合的交集
5	
def &~(that: Set[A]): Set[A]
返回兩個集合的差集
6	
def +(elem1: A, elem2: A, elems: A*): Set[A]
通過添加傳入指定集合的元素創建一個新的不可變集合
7	
def ++(elems: A): Set[A]
合併兩個集合
8	
def -(elem1: A, elem2: A, elems: A*): Set[A]
通過移除傳入指定集合的元素創建一個新的不可變集合
9	
def addString(b: StringBuilder): StringBuilder
將不可變集合的所有元素添加到字符串緩衝區
10	
def addString(b: StringBuilder, sep: String): StringBuilder
將不可變集合的所有元素添加到字符串緩衝區,並使用指定的分隔符
11	
def apply(elem: A)
檢測集合中是否包含指定元素
12	
def count(p: (A) => Boolean): Int
計算滿足指定條件的集合元素個數
13	
def copyToArray(xs: Array[A], start: Int, len: Int): Unit
複製不可變集合元素到數組
14	
def diff(that: Set[A]): Set[A]
比較兩個集合的差集
15	
def drop(n: Int): Set[A]]
返回丟棄前n個元素新集合
16	
def dropRight(n: Int): Set[A]
返回丟棄最後n個元素新集合
17	
def dropWhile(p: (A) => Boolean): Set[A]
從左向右丟棄元素,直到條件p不成立
18	
def equals(that: Any): Boolean
equals 方法可用於任意序列。用於比較系列是否相等。
19	
def exists(p: (A) => Boolean): Boolean
判斷不可變集合中指定條件的元素是否存在。
20	
def filter(p: (A) => Boolean): Set[A]
輸出符合指定條件的所有不可變集合元素。
21	
def find(p: (A) => Boolean): Option[A]
查找不可變集合中滿足指定條件的第一個元素
22	
def forall(p: (A) => Boolean): Boolean
查找不可變集合中滿足指定條件的所有元素
23	
def foreach(f: (A) => Unit): Unit
將函數應用到不可變集合的所有元素
24	
def head: A
獲取不可變集合的第一個元素
25	
def init: Set[A]
返回所有元素,除了最後一個
26	
def intersect(that: Set[A]): Set[A]
計算兩個集合的交集
27	
def isEmpty: Boolean
判斷集合是否爲空
28	
def iterator: Iterator[A]
創建一個新的迭代器來迭代元素
29	
def last: A
返回最後一個元素
30	
def map[B](f: (A) => B): immutable.Set[B]
通過給定的方法將所有元素重新計算
31	
def max: A
查找最大元素
32	
def min: A
查找最小元素
33	
def mkString: String
集合所有元素作爲字符串顯示
34	
def mkString(sep: String): String
使用分隔符將集合所有元素作爲字符串顯示
35	
def product: A
返回不可變集合中數字元素的積。
36	
def size: Int
返回不可變集合元素的數量
37	
def splitAt(n: Int): (Set[A], Set[A])
把不可變集合拆分爲兩個容器,第一個由前 n 個元素組成,第二個由剩下的元素組成
38	
def subsetOf(that: Set[A]): Boolean
如果集合A中含有子集B返回 true,否則返回false
39	
def sum: A
返回不可變集合中所有數字元素之和
40	
def tail: Set[A]
返回一個不可變集合中除了第一元素之外的其他元素
41	
def take(n: Int): Set[A]
返回前 n 個元素
42	
def takeRight(n: Int):Set[A]
返回後 n 個元素
43	
def toArray: Array[A]
將集合轉換爲數組
44	
def toBuffer[B >: A]: Buffer[B]
返回緩衝區,包含了不可變集合的所有元素
45	
def toList: List[A]
返回 List,包含了不可變集合的所有元素
46	
def toMap[T, U]: Map[T, U]
返回 Map,包含了不可變集合的所有元素
47	
def toSeq: Seq[A]
返回 Seq,包含了不可變集合的所有元素
48	
def toString(): String
返回一個字符串,以對象來表示

個人學習code

/**
 * Author TimePause
 * Create  2019-12-11 14:20
 */
object SetStudy {
  def main(args: Array[String]): Unit = {

    /**
     * 不可邊長
     */
    val set1 = Set[Int](1, 2, 3, 4, 5, 5, 5)
    println("遍歷方式一")
    set1.foreach(println)

    println("遍歷方式二")
    for (one <- set1){
      println(one)
    }

    println("----intersect:取交集----")
    val set2 = Set[Int](1, 2, 3)
    val set3 = Set[Int](1, 2, 3, 4, 5)
    val ints: Set[Int] = set2.intersect(set3)
    ints.foreach(println)
    println("----diff:差集,必須是大的集合差上小的集合----")
    val ints1: Set[Int] = set3.diff(set2)
    ints1.foreach(println)
    println("----%~作用和diff相同, 但這裏必須是小的差上大的集合---")
    val ints3: Set[Int] = set1 &~ set2
    ints3.foreach(println)

    /**
     * 可邊長
     * mutable:定位當前set爲可變的
     */
    println("----可邊長測試-----")
    val strings: mutable.Set[String] = mutable.Set[String]("ah", "sz", "xg")
    strings.add("wg")
    strings.add("tp")
    strings.foreach(println)



  }

}

四 Map

Map相關方法總結

Scala Map 方法
下表列出了 Scala Map 常用的方法:
序號	方法 描述
1	
def ++(xs: Map[(A, B)]): Map[A, B]
返回一個新的 Map,新的 Map xs 組成
2	
def -(elem1: A, elem2: A, elems: A*): Map[A, B]
返回一個新的 Map, 移除 key 爲 elem1, elem2 或其他 elems。
3	
def --(xs: GTO[A]): Map[A, B]
返回一個新的 Map, 移除 xs 對象中對應的 key
4	
def get(key: A): Option[B]
返回指定 key 的值
5	
def iterator: Iterator[(A, B)]
創建新的迭代器,並輸出 key/value 對
6	
def addString(b: StringBuilder): StringBuilder
將 Map 中的所有元素附加到StringBuilder,可加入分隔符
7	
def addString(b: StringBuilder, sep: String): StringBuilder
將 Map 中的所有元素附加到StringBuilder,可加入分隔符
8	
def apply(key: A): B
返回指定鍵的值,如果不存在返回 Map 的默認方法
10	
def clone(): Map[A, B]
從一個 Map 複製到另一個 Map
11	
def contains(key: A): Boolean
如果 Map 中存在指定 key,返回 true,否則返回 false。
12	
def copyToArray(xs: Array[(A, B)]): Unit
複製集合到數組
13	
def count(p: ((A, B)) => Boolean): Int
計算滿足指定條件的集合元素數量
14	
def default(key: A): B
定義 Map 的默認值,在 key 不存在時返回。
15	
def drop(n: Int): Map[A, B]
返回丟棄前n個元素新集合
16	
def dropRight(n: Int): Map[A, B]
返回丟棄最後n個元素新集合
17	
def dropWhile(p: ((A, B)) => Boolean): Map[A, B]
從左向右丟棄元素,直到條件p不成立
18	
def empty: Map[A, B]
返回相同類型的空 Map
19	
def equals(that: Any): Boolean
如果兩個 Map 相等(key/value 均相等),返回true,否則返回false
20	
def exists(p: ((A, B)) => Boolean): Boolean
判斷集合中指定條件的元素是否存在
21	
def filter(p: ((A, B))=> Boolean): Map[A, B]
返回滿足指定條件的所有集合
22	
def filterKeys(p: (A) => Boolean): Map[A, B]
返回符合指定條件的的不可變 Map
23	
def find(p: ((A, B)) => Boolean): Option[(A, B)]
查找集合中滿足指定條件的第一個元素
24	
def foreach(f: ((A, B)) => Unit): Unit
將函數應用到集合的所有元素
25	
def init: Map[A, B]
返回所有元素,除了最後一個
26	
def isEmpty: Boolean
檢測 Map 是否爲空
27	
def keys: Iterable[A]
返回所有的key/p>
28	
def last: (A, B)
返回最後一個元素
29	
def max: (A, B)
查找最大元素
30	
def min: (A, B)
查找最小元素
31	
def mkString: String
集合所有元素作爲字符串顯示
32	
def product: (A, B)
返回集合中數字元素的積。
33	
def remove(key: A): Option[B]
移除指定 key
34	
def retain(p: (A, B) => Boolean): Map.this.type
如果符合滿足條件的返回 true
35	
def size: Int
返回 Map 元素的個數
36	
def sum: (A, B)
返回集合中所有數字元素之和
37	
def tail: Map[A, B]
返回一個集合中除了第一元素之外的其他元素
38	
def take(n: Int): Map[A, B]
返回前 n 個元素
39	
def takeRight(n: Int): Map[A, B]
返回後 n 個元素
40	
def takeWhile(p: ((A, B)) => Boolean): Map[A, B]
返回滿足指定條件的元素
41	
def toArray: Array[(A, B)]
集合轉數組
42	
def toBuffer[B >: A]: Buffer[B]
返回緩衝區,包含了 Map 的所有元素
43	
def toList: List[A]
返回 List,包含了 Map 的所有元素
44	
def toSeq: Seq[A]
返回 Seq,包含了 Map 的所有元素
45	
def toSet: Set[A]
返回 Set,包含了 Map 的所有元素
46	
def toString(): String
返回字符串對象

個人學習code

/**
 * Author TimePause
 * Create  2019-12-11 14:59
 */
object MapStudy {
  def main(args: Array[String]): Unit = {
    /**
     * 不可變長
     * map:k-v, 初始化方式可以爲k->v(將k映射到v上), (k,v)
     * 因此在遍歷語句 for循環中, elem<-map代表將mao集合中的所有元素映射到elem上, 然後我們通過${elem._1},${elem._2}獲取其k,v值
     */
      val map=Map[String,Int]("chy"->18,"zwer"->19,("xy",20),("xy",21))
      for (elem<-map){
        println(s"key=${elem._1} ,value=${elem._2}")
      }

    println("獲取map的v, 如果有返回Some(v),沒有返回None. 可以再通過一個get去除Some")
    val maybeInt: Option[Int] = map.get("chy")
    val maybeInt2= map.get("chy").get
    //如果能找到k,返回v,找不到返回666,返回參數可自定義
    val maybeInt3= map.get("chy1").getOrElse(666)
    println(maybeInt)
    println(maybeInt2)
    println(maybeInt3)

    println("keys : 用於獲取所有key")
    val keys: Iterable[String] = map.keys
    keys.foreach(println)   //只獲取k
    for (key<-keys){
      println(s"key:${key}, value:${map.get(key).getOrElse(666)}")  //同時獲取k,v
    }

    println("values: 獲取所有value")
    val values: Iterable[Int] = map.values
    values.foreach(println)

    println("set中的filter方法,count等方法這裏也有")
    val stringToInt: Map[String, Int] = map.filter(tp => {
      "chy".equals(tp._1)
    })
    stringToInt.foreach(println)

    println("++將後面的map放到前面的map, ++: 則是相反(貌似現在用不了了)")
    val map1=Map[String,Int]("a站"->6,"b站"->8,"c站"->7)
    val map2=Map[String,Int]("a站"->66,"b站"->88,"c站"->77,("d站",99))
    val mapadd: Map[String, Int] = map1.++(map2)
    for (tp<-mapadd){
      println(s"k=${tp._1},value:${tp._2}")
    }


    /**
     * 可邊長map
     */
      println("可邊長map-----------")
    val muMap: mutable.Map[String, Int] = mutable.Map[String, Int](("a", 1))
    muMap.put("b",2)
    muMap.foreach(println)
  }
}

五 元組

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

  2. 創建元組與取值
    val tuple = new Tuple(1) 可以使用new
    val tuple2 = Tuple(1,2) 可以不使用new,也可以直接寫成val tuple3 =(1,2,3)
    取值用”._XX” 可以獲取元組中的值
    注意:tuple最多支持22個參數

  3. 元組的遍歷
    tuple.productIterator得到迭代器,進而遍歷

  4. swap,toString方法
    注意:swap元素翻轉,只針對二元組

  /**
   * Author TimePause
   * Create  2019-12-11 17:28
   */
  object TupleStudy {
    def main(args: Array[String]): Unit = {
      /**
       *Tuple:元組 與list一樣,只不過每個元素都對應一個類型. 最多支持22個元素
       * 注意:
       *    1. 定義tuple時, 三種方式new,也可以不用new,直接寫()填寫元素,最多22個
       *    2. tuple[n] : n 代表tuple中需要添加元素的個數
       *    3. tuple取值, tuple位置
       *    4. 遍歷tuple:使用tuple.productIterator 得到一個迭代器, 遍歷迭代器即可
       */
        println("------------tuple創建元組與取值-------------")
      val tuple: Tuple1[String] = new Tuple1("hello")
      val tuple2: (String, Int) = new Tuple2("hello", 10)
      //    println(s"key = ${tuple2._1},value = ${tuple2._2}")

      val tuple3 = new Tuple3(1, true, 1.5f)
      println("---"+tuple3.toString())
      val tuple4 = new Tuple4(1,2,3,4)
      val tuple5 = Tuple5(1,2.5f,"hello world",'c',true)
      //    println(tuple5._5)
      val tuple6 = (1,2,3,4,"hello world",6,7,8)
      //    println(tuple6._5)
      val tuple22: (Int, Boolean, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) = (1, true, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22)

      println("---------tuple的遍歷---------")
      val iter: Iterator[Any] = tuple5.productIterator
      iter.foreach(println)
      //    while(iter.hasNext){
      //      println(iter.next())
      //    }

      /**
       * 注意:swap元素翻轉,只針對二元組
       */
      println(tuple2.swap)

    }
  }


第六章 Scala 高級知識

一 trait 特性

  1. 概念理解
    Scala Trait(特徵) 相當於 Java 的接口,實際上它比接口還功能強大。
    與接口不同的是,它還可以定義屬性和方法的實現。
    一般情況下Scala的類可以繼承多個Trait,從結果來看就是實現了多重繼承。Trait(特徵) 定義的方式與類類似,但它使用的關鍵字是 trait。
  2. 舉例:trait中帶屬性帶方法實現
    注意:
    繼承的多個trait中如果有同名的方法和屬性,必須要在類中使用“override”重新定義。
    trait中不可以傳參數
  3. 舉例:trait中帶方法不實現

學習code

/**
 * trait中可以定義變量和常量, 也可以定義方法的實現和不實現, 一個類可以繼承多個trait
 *  注意: 一個類繼承多個trait時, 第一個使用 extends,後面的使用 with
 *
 * Author TimePause
 * Create  2019-12-11 19:41
 */
//案例一
trait Read{
 // val age=1
  def read(name:String): Unit ={
    println(s"$name is reading...")
  }
}

trait Listen{
 // val age=2
  def listen(name:String): Unit ={
    println(s"$name is listenning")
  }
}
class Persons(xname:String,age:Int) extends Read with  Listen {
  val name=xname
 // override val age: Int = 30
}

//案例二
trait MyEQU{
  def isEQU(o:Any):Boolean
  def isNotEQU(o:Any):Boolean= !isEQU(o)
}
class  Point(xx:Int,xy:Int) extends  MyEQU {
    val x=xx;
    val y=xy;

  override def isEQU(o: Any): Boolean = {
    // isInstanceOf是否是某個類. asInstanceOf作爲後面的類型
    o.isInstanceOf[Point]&& o.asInstanceOf[Point].x==this.x;
  }
}

object TraitStudy {
  def main(args: Array[String]): Unit = {
    val persons: Persons = new Persons("tp", 18)
    persons.read("tp")
    persons.listen("tp")

    val p1=new Point(1,2)
    val p2=new Point(1,3)
    println(p1.isEQU(p2))
    println(p1.isNotEQU(p2))
  }
}

二 樣例類 CaseClass

概念理解
使用了case關鍵字的類定義就是樣例類(case classes),樣例類是種特殊的類。實現了類構造參數的getter方法(構造參數默認被聲明爲val),當構造參數是聲明爲var類型的,它將幫你實現setter和getter方法。

  • 樣例類默認幫你實現了toString,equals,copy和hashCode等方法。
  • 樣例類可以new, 也可以不用new
/**
 * 樣例類
 * 樣例類默認實現了toString,equals,copy和hashCode等方法
 * 樣例類可以使用new 創建, 也可以不使用
 *
 * Author TimePause
 * Create  2019-12-11 20:22
 */
case class man(xname:String,xage:Int){

}

object CaseClassStudy {
  def main(args: Array[String]): Unit = {
    val h1 =new man("chy",22)
    val h2 =man("chy",22)
    println(h1.equals(h2))
  }
}

三 模式匹配 Match

  1. 概念理解:
    Scala 提供了強大的模式匹配機制,應用也非常廣泛。
    一個模式匹配包含了一系列備選項,每個都開始於關鍵字 case。
    每個備選項都包含了一個模式及一到多個表達式。箭頭符號 => 隔開了模式和表達式。

  2. 代碼及注意點
    模式匹配不僅可以匹配值還可以匹配類型
    從上到下順序匹配,如果匹配到則不再往下匹配
    都匹配不上時,會匹配到case _ ,相當於default
    match 的最外面的”{ }”可以去掉看成一個語句

  3. 偏函數
    如果一個方法中沒有match 只有case,這個函數可以定義成PartialFunction偏函數。偏函數定義時,不能使用括號傳參,默認定義PartialFunction中傳入一個值,匹配上了對應的case,返回一個值,只能匹配同種類型。

/**
 *
 * match scala中的模式匹配
 *   注意:
 *     1.Scala中的模式匹配關鍵字是Match
 *     2.Match模式匹配中不僅可以匹配值,還可以匹配類型,且可以混在一起寫。
 *     3.case _=>{.. .. .}代表什麼都匹配不上的默認匹配,放在最後
 *     4.匹配的過程中,如果匹配上之後會自動終止。
 *     5.Match匹配的過程中有數值的轉換
 */
object MatchStudy {
  def main(args: Array[String]): Unit = {
    val tuple = (1, 1.1, true, "hello", 'c', 1.4f)
    val iter: Iterator[Any] = tuple.productIterator
    iter.foreach(MatchTest)
  }

  /**
   * MatchTest只是一個方法,重要的是方法裏面的 match...case語句
   * _代表如果匹配所有,在這裏的意思是如果前面的都沒有匹配到,匹配這裏(默認值)
   */
  def MatchTest(o:Any) =
    o match {
      case i:Int=>println(s"type is Int ,value is $i")
      case 1 =>println("value is 1")
      case b:Boolean=>println(s"type is Boolean ,value is $b")
      case d:Double =>println(s"type is Double ,value is $d")
      case "hello"=>println("value is hello")
      case 'c'=>{println("value is c")}
      case _=>println("no ... match ... ")

    }

	/**
	  * 一個函數中只有case 沒有match ,可以定義成PartailFunction 偏函數
	  */
	object Lesson_PartialFunction {
	  def MyTest : PartialFunction[String,String] = {
	    case "scala" =>{"scala"}
	    case "hello"=>{"hello"}
	    case _=> {"no  match ..."}
	  }

}

在這裏插入圖片描述

四 偏函數

如果一個方法中沒有match 只有case,這個函數可以定義成PartialFunction偏函數。偏函數定義時,不能使用括號傳參,默認定義PartialFunction中傳入一個值,匹配上了對應的case,返回一個值,只能匹配同種類型。

/**
 * 偏函數, 完全類似java中的switch...case...語句
 *
 * Author TimePause
 * Create  2019-12-12 9:12
 */
object PartitionFunStudy {
  def MyFun:PartialFunction[String,String]={
    case "1" =>{"一等獎"}
    case "2"=>{"二等獎"}
    case "3"=>{"三等獎"}
    case _=>{"優秀獎"}
  }

  def main(args: Array[String]): Unit = {
    println(MyFun("ss"))

  }
}

五 隱式轉換

隱式轉換是在Scala編譯器進行類型匹配時,如果找不到合適的類型,那麼隱式轉換會讓編譯器在作用範圍內自動推導出來合適的類型。

1. 隱式值與隱式參數
隱式值是指在定義參數時前面加上implicit。隱式參數是指在定義方法時,方法中的部分參數是由implicit修飾【必須使用柯里化的方式,將隱式參數寫在後面的括號中】。隱式轉換作用就是:當調用方法時,不必手動傳入方法中的隱式參數,Scala會自動在作用域範圍內尋找隱式值自動傳入。

隱式值和隱式參數注意:

  • 同類型的參數的隱式值只能在作用域內出現一次,同一個作用域內不能定義多個類型一樣的隱式值。
  • implicit 關鍵字必須放在隱式參數定義的開頭
  • 一個方法只有一個參數是隱式轉換參數時,那麼可以直接定義implicit關鍵字修飾的參數,調用時直接創建類型不傳入參數即可。
  • 一個方法如果有多個參數,要實現部分參數的隱式轉換,必須使用柯里化這種方式,隱式關鍵字出現在後面,只能出現一次

2.隱式轉換函數

隱式轉換函數是使用關鍵字implicit修飾的方法。當Scala運行時,假設如果A類型變量調用了method()這個方法,發現A類型的變量沒有method()方法,而B類型有此method()方法,會在作用域中尋找有沒有隱式轉換函數將A類型轉換成B類型,如果有隱式轉換函數,那麼A類型就可以調用method()這個方法。

隱式轉換函數注意:隱式轉換函數只與函數的參數類型和返回類型有關,與函數名稱無關,所以作用域內不能有相同的參數類型和返回類型的不同名稱隱式轉換函數。

3. 隱式類
使用implicit關鍵字修飾的類就是隱式類。若一個變量A沒有某些方法或者某些變量時,而這個變量A可以調用某些方法或者某些變量時,可以定義一個隱式類,隱式類中定義這些方法或者變量,隱式類中傳入A即可。

隱式類注意:

  • .隱式類必須定義在類,包對象,伴生對象中。
  • 隱式類的構造必須只有一個參數,同一個類,包對象,伴生對象中不能出現同類型構造的隱式類。
/**
 * 隱式轉換implicit
 *  1.隱式值和隱式參數
 *      1)作用域內,相同類型的隱式值只能聲明一個
 *      2)一個方法中部分參數是隱式參數, 只能使用科裏化方式來定義.將隱式的參數單獨放到一個參數表中,不需要的放第一個括號裏,使用時直接賦值即可
 *      3)調用隱式方法時, 可以覆蓋隱式參數/*  2.隱式轉換函數
 *      作用域中不能有相同的 參數類型 和 返回類型 的不同名稱的隱式轉換函數
 *  3.隱式類
 *      在類的前面加上關鍵字implicit, 必須定義在objectclass*      隱式類中的所有屬性方法都可以被調用
 *      隱式類和隱式轉換函數非常像
 *
 * Author TimePause
 * Create  2019-12-12 9:27
 */
object Implicitl {
  implicit  var name="TimePause"
  implicit  var age=18

  //案例一
  def people(implicit name:String): Unit ={
    println(s"Hello ${name}")
  }

  def people2(sex:String)(implicit name:String,age:Int): Unit ={
    println(s"Hello ${name}, age:${name}, sex: ${sex}")
  }

  //案例二
  class Bird(bname:String){
    var name=bname;
    def canFly(): Unit ={
        println(s"${name} able fly!")
    }
  }
  class  Pig(pname:String){
    var name=pname
  }

  //案例三
 implicit class Bird1(p:Pig1){
    var name=p.name
    var pvalue="9.15"
    def canFly(): Unit ={
      println(s"${name} able fly!")
    }
  }
  class  Pig1(pname:String){
    var name=pname
  }


  def main(args: Array[String]): Unit = {
    people
    people2("男")

    //使用隱式轉換函數(p:Pig): Bird, pig是規定傳入參數的類型, Bird規定的返回值的類型
    // 令我們可以通過pig調用bird的fly方法
    implicit  def pigToBird(p:Pig): Bird ={
        new Bird(p.name)
    }
    val pig = new Pig("yyx")
    pig.canFly()

    //重點掌握上面兩種即可
    val pig1 = new Pig1("wwk")
    pig1.canFly()
    pig1.pvalue
  }
}

在這裏插入圖片描述

六 Actor Model (Actor通信模型)

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

Actor的特徵:

  • ActorModel是消息傳遞模型,基本特徵就是消息傳遞
  • 消息發送是異步的,非阻塞的
  • 消息一旦發送成功,不能修改
  • Actor之間傳遞時,自己決定決定去檢查消息,而不是一直等待,是異步非阻塞的
  • Actor被實例化後只能用於給自身類發送信息

什麼是Akka
Akka 是一個用 Scala 編寫的庫,用於簡化編寫容錯的、高可伸縮性的 Java 和Scala 的 Actor 模型應用,底層實現就是Actor,Akka是一個開發庫和運行環境,可以用於構建高併發、分佈式、可容錯、事件驅動的基於JVM的應用。使構建高併發的分佈式應用更加容易。
spark1.6版本之前,spark分佈式節點之間的消息傳遞使用的就是Akka,底層也就是actor實現的。1.6之後使用的netty傳輸。

import scala.actors.Actor

/**
 * Actor通信模型
 * 需要準備, 面試可能會要求要寫, 以備不時之需
 *
 * 步驟
 *  1.創建兩個class,繼承Actor, 重新act()方法, 在方法內書寫業務邏輯 receive方法代表接收器case匹配聊天內容
 *  2.Actor被實例化後只能用於給自身發送信息. 因爲如果要給其他人發送信息需要有 ip+port
 *  3.如果需要給其他Actor發送信息, 需要在自己的Actor實現類中實例化對方類, 通過對方類的對象來給自己發送信息
 *  4.樣例類MSG2 : 相當於java中的實體類, 用於規定規定case接收的數據類型模型
 *  5.在Scala類中實例化上面兩個類,啓動Actor線程
 */
case class MSG2(actor : Actor, msg : String)

class MyActor3 extends  Actor{
  override def act(): Unit = {
    while(true) {
      receive{
        case m : MSG2  =>{
          println(m.msg)
          val actor4 = m.actor
          actor4 ! "hello"
        }
        case s:String=>{println(s"MyActor3 say:${s}")}
        case _=>{println("MyActor receiveMessage fail")}
      }
    }
  }
}
class MyActor4(act3:Actor) extends  Actor{
  act3 ! MSG2(this, "MyActor4: hi Actor3")
  override def act(): Unit = {
    while(true) {
      receive{
        case s:String=>{
          if (s.equals("hello")) {
             println("MyActor4: hi")
          }
        }
        case _=>{println("MyActor sendMessage fail")}
      }
    }
  }
}

object TestActorForMe {
  def main(args: Array[String]): Unit = {
    val actor3 = new MyActor3()
    actor3 !"hello"
    val actor4 = new MyActor4(actor3)
    actor3.start()
    actor4.start()

  }
}

在這裏插入圖片描述


第七章 搭建Spark運行環境

一 環境搭建

  1. 安裝並配置Maven(本人java高級技術中有)

  2. Idea創建Maven項目,選擇 quickstart
    在這裏插入圖片描述

  3. 將原來pom文件中 properties文件及以下刪除, 換爲本人上傳的 Spark的pom配置文件, 稍等片刻待系統緩存相關jar包

  4. 緩存完成後, 在main目錄下新建一個 scala 目錄, 用於編寫scala代碼實現Spark, 和java代碼進行比較

  5. 打開 Project Stucture 設置,按下圖將scala目錄提升爲可編譯的源目錄
    在這裏插入圖片描述

  6. 書寫代碼

二 WordCount實現(Scala)

非簡化版

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

/**
 * 非簡化版
 *匿名函數只有一次可以用下劃線簡化進行表示
 * Author TimePause
 * Create  2019-12-12 19:17
 */
object SparkWordCount {
  def main(args: Array[String]): Unit = {
    // 創建Spark的配置文件
    val conf: SparkConf = new SparkConf()
    conf.setMaster("local")
    conf.setAppName("SparkWordCount")
    val context = new SparkContext(conf)

    val lines: RDD[String] = context.textFile("./data/word.txt")
    val words: RDD[String] = lines.flatMap(line => {
      line.split(" ")
    })
    // 將word字符串放到二元組中,key代表單詞,v代表該單詞出現次數
    val wordMap: RDD[(String, Int)] = words.map(word => {
      Tuple2(word, 1)
    }) 

    // 按照相同的key進行分組, 在對每個組的v進行操作
    val result: RDD[(String, Int)] = wordMap.reduceByKey((v1, v2) => {
      v1 + v2
    })
    /*對結果進行排序,默認true,正序*/
    val value = result.sortBy(tp => tp._2, false)
    /*通過swap轉換然後通過sortByKey進行排序*/
    //val value = result.map(tp => {tp.swap}) .sortByKey(false)  //or   result.map(tp=>{tp._2,tp._1})
    value.foreach(println)

    //釋放SparkContext的對象
    context.stop();
  }
}

簡化版

必須熟練默寫, 面試必會!!!

**
 * 簡化版
 *匿名函數只有一次可以用下劃線簡化進行表示
 * Author TimePause
 * Create  2019-12-12 19:17
 */
object SparkWordCount2 {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setMaster("local").setAppName("SparkWordCount")
    val context = new SparkContext(conf)
    val lines = context.textFile("./data/word.txt").flatMap(_.split(" ")).map((_, 1)).reduceByKey(_+_).sortBy(_._2,false).foreach(println)
    context.stop();
  }
}

三 WordCount實現(Java)

非簡化版

基於Scala實現wordcount:非簡化版
JavaRDD: 某種類型的RDD
mapTOPair->將非kv格式rdd轉成kv格式rdd
reduceByKey必須作用在PairRDD上
JavaPairRDD :二元組類型RDD,k,v

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.FlatMapFunction;
import org.apache.spark.api.java.function.Function2;
import org.apache.spark.api.java.function.PairFunction;
import org.apache.spark.api.java.function.VoidFunction;
import scala.Tuple2;

import java.util.Arrays;
import java.util.Iterator;

/**
 * Java實現Spark方式的wordcount
 *
 * @author TimePause
 * @create 2019-12-12 21:20
 */
public class JavaWordCount {
    public static void main(String[] args) {
        /**
         * SparkConf就是Spark的配置信息,可以配置以下內容:
         *  1.可以配置Spark的運行模式
         *       local:本地運行, 多用於測試, 在eclipse, Idea中使用 SParkConf.setMaster("local")
         *       standalone:Spark自帶的資源調度框架, 支持分佈式搭建, Spark任務可以運行在Standalone, 集羣命令提交
         *       yarn:Hadoop生態圈中的資源調度框架, Spark可以運行在yarn, 集羣命令提交
         *       mesos:資源調度框架
         *  2.配置當前application運行的名稱 conf.setAppName("wc")
         *  3.配置當前application資源使用信息, conf.set(K,V)
         */
        SparkConf conf = new SparkConf();
        conf.setMaster("local");
        conf.setAppName("wc");
        // javaSparkContext: 是Spark的上下文, 通過集羣的唯一通道
        JavaSparkContext sc = new JavaSparkContext(conf);
        JavaRDD<String> lines = sc.textFile("./data/word.txt");
        // 將單詞分詞
        JavaRDD<String> words = lines.flatMap(new FlatMapFunction<String, String>() {
            @Override
            public Iterator<String> call(String line) throws Exception {
                return Arrays.asList(line.split(" ")).iterator();
            }
        });

        //使用mapToPair將JavaRDD轉成JavaPairRDD
        //轉換後使用tuple返回, 且key爲單詞名稱, value爲詞頻
        JavaPairRDD<String, Integer> javaPairRDD = words.mapToPair(new PairFunction<String, String, Integer>() {
            @Override
            public Tuple2<String, Integer> call(String word) throws Exception {
                return new Tuple2<String, Integer>(word, 1);
            }
        });

        // 按照相同的key進行分組, 在對每個組的v進行操作
        JavaPairRDD<String, Integer> reduceResult = javaPairRDD.reduceByKey(new Function2<Integer, Integer, Integer>() {
            @Override
            public Integer call(Integer v1, Integer v2) throws Exception {
                return v1 + v2;
            }
        });
        //排序操作1, 放入一個tuple數據, 返回一個kv數據
        JavaPairRDD<Integer, String> swapRDD = reduceResult.mapToPair(new PairFunction<Tuple2<String, Integer>, Integer, String>() {
            @Override
            public Tuple2<Integer, String> call(Tuple2<String, Integer> integerStringTuple2) throws Exception {
                return integerStringTuple2.swap();
            }
        });
        //排序操作2,調用api的sortByKey
        JavaPairRDD<Integer, String> sortByKeyRDD = swapRDD.sortByKey(false);
        //排序操作3,將排序好的集合再次轉換成二元組
        JavaPairRDD<String, Integer> result = sortByKeyRDD.mapToPair(new PairFunction<Tuple2<Integer, String>, String, Integer>() {
            @Override
            public Tuple2<String, Integer> call(Tuple2<Integer, String> integerStringTuple2) throws Exception {
                return integerStringTuple2.swap();
            }
        });

        result.foreach(new VoidFunction<Tuple2<String, Integer>>() {
            @Override
            public void call(Tuple2<String, Integer> tuple2) throws Exception {
                System.out.println(tuple2);
            }
        });
        sc.stop();
    }
}

簡化版

public class SparkWordCount {
    public static void main(String[] args) {

        SparkConf conf = new SparkConf();
        conf.setMaster("local");
        conf.setAppName("wc");
        JavaSparkContext sc = new JavaSparkContext(conf);
        sc.textFile("./data/words").flatMap(line -> Arrays.asList(line.split(" ")).iterator()).mapToPair(word -> new Tuple2<>(word, 1)).reduceByKey((v1, v2) -> v1 + v2).foreach(tuple2 -> System.out.println(tuple2));

        sc.stop();

//        SparkConf conf = new SparkConf();
//        conf.setMaster("local");
//        conf.setAppName("wc");
//        JavaSparkContext sc = new JavaSparkContext(conf);
//        JavaRDD<String> lines = sc.textFile("./data/words");
//        JavaRDD<String> words = lines.flatMap(line -> Arrays.asList(line.split(" ")).iterator());
//
//        JavaPairRDD<String, Integer> pairWords = words.mapToPair(word -> new Tuple2<>(word, 1));
//
//        JavaPairRDD<String, Integer> result = pairWords.reduceByKey((v1, v2) -> v1 + v2);
//        result.foreach(tuple2 -> System.out.println(tuple2));
//
//        sc.stop();


    }
}


鏈接:https://pan.baidu.com/s/1XNIbgV6dMF9_hVrcLrga4A
提取碼:ef0f

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章