Scala 基礎(6)—— 控制結構

1. Scala 的內建控制結構java

Scala 有幾個內建的控制結構,包括:編程

  • if 表達式
  • while 循環和 do-while 循環
  • for 表達式
  • try 表達式
  • match 表達式

Scala 的全部控制結構都返回某種值做爲結果,這是函數式編程採起的策略:ide

程序是被用來計算出某個值,因此程序的各個組成部分也應該計算出某個值。函數式編程

 

以上的5個控制結構中,有一個被稱之爲循環,而不是表達式,由於它不會返回一個有意義的值。函數

while 和 do-while 的返回值的類型永遠都是 Unit,即單元值,寫做 ()。Scala 的賦值語句的結果也是 ()。spa

 

2. if 表達式blog

if 表達式的使用方法,大體與 Java 相同。排序

有一個區別於 Java 的使用方法,就是因爲 if 表達式有返回值,因此在某些場景下能夠用來賦值:資源

  def main(args: Array[String]): Unit = {
    val fileName = if (args.isEmpty) args(0) else "default"
  }

 

3. while 和 do-while 循環字符串

while 和 do-while 循環的使用方法,也大體與 Java 相同。

可是這裏須要注意的是,因爲循環的結果永遠都是 Unit,因此從函數式編程的角度,不建議使用循環,由於這麼作純粹是爲了程序的反作用。

while 循環一般用來更新一個 var 的值,因此二者不少時候都是成對出現。

 

4. for 表達式

for 表達式主要用於迭代。

4.1 遍歷集合

for 表達式最多見的場景就是遍歷一個集合(包括 List,Set,Map,Array)

  def main(args: Array[String]): Unit = {
    val list = List(1, 2, 3)
    for (i <- list) println(i)

    val map = Map(1 -> "1.1", 2 -> "2.2")
    for ((k, v) <- map) println(k + "," + v)
  }

 

4.2 遍歷區間

for 表達式還能夠用來遍歷區間 Range,這是一種對於 Int 類的富包裝。

  def main(args: Array[String]): Unit = {
    for (i <- 1 to 3) print(i) // 輸出123
    for (i <- 1 until 3) print(i) // 輸出12
  }

其中 until 和 to 的區別在於:until 不包含上界,to 包含上界。

也可使用區間來遍歷集合,但這種用法在 Scala 中不推薦:

  def main(args: Array[String]): Unit = {
    val list = List(1, 2, 3)
    for (i <- 0 until list.length) println(list(i)) // 不推薦
  } 

 

4.3 過濾

遍歷集合時,能夠給 for 表達式增長 filter,具體的作法是在 for 表達式的圓括號中加一個 if 子句:

  def main(args: Array[String]): Unit = {
    val list = List(1, 2, 3)
    for (i <- list if i > 1) println(i)  // 輸出23
  }

支持同時使用多個 filter:

  def main(args: Array[String]): Unit = {
    val list = List(1, 2, 3)
    for (i <- list if i > 1 if i % 2 == 0) println(i) // 輸出2
  }

 

4.4 嵌套迭代

for 表達式內部能夠寫多個 <- 子句,表示嵌套迭代。

這裏寫一個典型的嵌套迭代:冒泡排序

  def main(args: Array[String]): Unit = {
    val array = Array(4, 2, 5, 1, 3)
    bubble(array)
    for (i <- array) print(i)

  }

  def bubble(array: Array[Int]) = {
    for (i <- 0 until array.length - 1; // 注意,嵌套迭代之間的分號是不能省略的
         j <- 0 until array.length - i - 1 if array(j) > array(j + 1)) swap(array, j, j + 1)
  }

  def swap(array: Array[Int], i: Int, j: Int) = {
    val temp = array(i)
    array(i) = array(j)
    array(j) = temp
  }

須要注意的是:

  • 若是 for 表達式使用圓括號,嵌套迭代之間的分號是不能省略的。
  • 若是 for 表達式使用花括號,嵌套迭代之間的分號能夠省略。
  • 外循環與內循環之間除了使用過濾器,或者中途變量綁定,不能增長其餘操做。

所謂中途變量綁定,就是用 = 在 for 表達式內部進行臨時的變量綁定(使用這個技巧能夠在循環之間增長額外的操做)

  def bubble(array: Array[Int]) = {
    for {i <- 0 until array.length - 1
         // println() 編譯出錯
         a = println() // 編譯成功
         j <- 0 until array.length - i - 1 if array(j) > array(j + 1)} swap(array, j, j + 1)
  }

 

4.5 yield

for 表達式在每次迭代中,均可以生成一個能夠被記住的值,具體的作法實在 for 表達式的代碼體以前使用 yield 關鍵字。

交出的值,被統一存儲在一個集合裏面,這個集合的類型取決於迭代子句中處理的集合種類:

  def main(args: Array[String]): Unit = {
    val array = Array(1, 2, 3)
    val a = for (i <- array if i % 2 == 0) yield i // a是Array

    val list = List(1, 2, 3)
    val b = for (i <- array if i % 2 == 0) yield i // b是List
  }

 

5. try 表達式

try 表達式用來處理異常狀況,與 Java 基本相同,是 try-catch-finally 結構。

try 表達式在 catch 模塊與 Java 的語法不相同:

  def myDivide(a: Int, b: Int): Int = {
    try {
      if (a < 0 || b < 0) throw new Exception else a / b
    } catch {
      case ex: ArithmeticException => -1
      case ex: Exception => -2 // 這行註釋掉編譯也不會出現問題
    } finally {
      println("Go to finally")
    -3 } }

try-catch-finally 結構也會交出一個值,可是 finally 中的語句雖然始終被執行,可是卻和交出值沒有關係。

例如:

  def main(args: Array[String]): Unit = {
    println(myDivide(2, -1)) // 結果是 -2
  }

 所以咱們能夠作一個初步的總結:

  • try 表達式用於異常捕獲。
  • Scala 的受檢異常(checked exception),從編譯的角度上不強制要求咱們 catch,這點和 Java 不同。
  • catch 子句遵循模式匹配用法。
  • try 表達式能夠交出一個值。
  • finally 子句始終會被執行,可是不參與交出值,因此通常用來作資源回收之類的工做。

 

6. match 表達式

Scala 的 match 表達式,從控制結構的角度上講,對應的是 Java 的 switch-case 結構。

固然 match 表達式的做用不只限於此,它屬於 Scala 的模式匹配的其中一種用法,此處不展開。

  def main(args: Array[String]): Unit = {
    val str = if (args.length > 0) args(0) else "default"
    val firstArg = str match {
      case "1" => "one"
      case "default" => "zero"
      case _ => "nothing" // 和 Java 中的 default 關鍵字起相同的做用
    }
    println(firstArg)
  }

Scala 的 match 表達式和 Java 的 switch-case 結構有三處區別:

  • Scala 中的任何常量、字符串均可以做爲 match 表達式匹配的樣例。
  • Scala 的 match 表達式每一個可選象後面不須要有 break。
  • Scala 的 match 表達式有返回值。

 

7. break & continue

Scala 語言裏,沒有 break 和 continue 關鍵字。

因此若是須要相似的語義,在使用 while 或 do-while 循環,或是 for 表達式的時候,須要對程序作必定的修改。

最簡單的解決方案是:

  • 用 if 換掉每個 continue。
  • 用布爾值取代 break。
相關文章
相關標籤/搜索