1. 程式人生 > >【圖文詳細 】Scala——基本語法

【圖文詳細 】Scala——基本語法

3、Scala 基礎語法 

3.1、Hello Scala 

package com.mazh.scala.helloworld 
 
/** 
  * 作者: 李濤: https://blog.csdn.net/qq_42246689 
  */ 
object HelloWorld { // 作用類似於 J ava 的 main 方法 
  def main(args: Array[String]): Unit = { 
    println("hello world") 
  } }

關於 HelloWorld 程式:Scala 和 Java 的對比不同處 

1、檔案字尾名

2、編譯和執行方式

3、類的宣告

4、main 方法的宣告

5、分號  

 

3.2、變數定義 

package com.mazh.scala.core 
 
/** 
  * 作者: 李濤: https://blog.csdn.net/qq_42246689 
  */ 
object VariableDemo { 
  def main(args: Array[String]) { 
    // 使用 val
定義的變數值是不可變的,相當於 java
裡用 final
修飾的變數 
    val i = 1 
    // 使用 var
定義的變數是可變得,在 Scala
中鼓勵使用 val 
    var s = "hello" 
    //Scala
編譯器會自動推斷變數的型別,必要的時候可以指定型別 
    // 變數名在前,型別在後     val str: String = "spark" 
  } 
}

總結:

1)資料型別可以指定,也可以不指定,如果不指定,那麼就會進行資料型別的自動推斷。

2)如果指定資料型別,資料型別的執行方式是在變數名後面寫一個冒號,然後寫上資料類 型。

3)我們的 scala 裡面變數的修飾符一共有兩個,一個是 var,一個是 val 如果是 var 修飾的變數,那麼這個變數的值是可以修改的 如果是 val 修飾的變數,那麼這個變數的值是不可以修改的 

懶載入:兩個例子 

scala> import scala.io.Source import scala.io.Source 
 
scala> lazy val file = Source.fromFile("/home/hadoop/student.txt") file: scala.io.BufferedSource = <lazy> 
 
scala> file res2: scala.io.BufferedSource = non-empty iterator 
 
scala> for (f <- file.getLines) println(f) 
95002,劉晨,女,19,IS 
95017,王風娟,女,18,IS 
95018,王一,女,19,IS 
95013,馮偉,男,21,CS 
95014,王小麗,女,19,CS 
95019,邢小麗,女,19,IS 
95020,趙錢,男,21,IS 
95003,王敏,女,22,MA 
95004,張立,男,19,IS 
95012,孫花,女,20,CS 
95010,孔小濤,男,19,CS 
95005,劉剛,男,18,MA 
95006,孫慶,男,23,CS 
95007,易思玲,女,19,MA 
95008,李娜,女,18,CS 
95021,週二,男,17,MA 
95022,鄭明,男,20,MA 
95001,李勇,男,20,CS 
95011,包小柏,男,18,MA 
95009,夢圓圓,女,18,MA 
95015,王君,男,18,MA       

 

3.3、資料型別 

3.3.1、資料型別概述 

Scala 和 Java 一樣,有 7 種數值型別 Byte、Char、Short、Int、Long、Float 和 Double(無包 裝型別)和一個 Boolean 型別,再加上常用的 String 型別 
 
資料型別:http://www.runoob.com/scala/scala-data-types.html

注意:scala 裡面沒有基本資料型別和包裝型別之說。

如果大家非要說的話,那麼大家都可以認為都有的型別的型別都是包裝型別。 

package com.mazh.scala.core 
 
/** 
  * 作者: 李濤: https://blog.csdn.net/qq_42246689 
  */ 
object TypeDemo { 
 
  def main(args: Array[String]): Unit = { 
 
    val var_int = 1 
    val var_double = 3.33 
    val var_float = 2.4F 
    val var_char = 'A' 
    val var_bool = true 
 
    val var_16 = 0x29 
    val var_string = "aa" 
    val var_string1 = "\"huangbo\"" 
    val var_string2 = """hello\thello\na\t\\""" 
    println (var_string2) 
  } 
} 

要點:

1、 Any 是所有類的父類,包括值型別 AnyVal,和引用型別 AnyRef

2、 AnyVal 是所有值型別的父類,包括 Int,Double,Boolean,Unit 等等

3、 AnyRef 是所有引用型別的父類,包括 Null

4、 Null 是所有引用型別的子類

5、 Nothing 是所有類的子類

6、 Unit 型別只有一個例項,是(),相當於 java 中的 void,沒有任何的實質意義

7、 Null 也只有一個例項,是 null,相當於 java 中的 null,能賦值給任何引用型別變數,不 能賦值給值型別變數 

3.3.2、Scala 基本型別操作 
算術操作:+   -   *   /   %  //  關係運算:>   >=   <   <=   ==   != 邏輯運算:&&   ||   ! 位運算: &   |   ^   ~   >>   <<  >>> 物件比較:1==1   1==1.0   "huangbo" == "huangbo"    ne   eq 
 
特別注意:ne eq equals == 
3.4、編碼規範 
1、分號:在 scala 編碼中,不強制在程式碼末尾加分號,但是如果有多句程式碼寫在同一行,那

麼必須使用分號進行隔開 
 
2、註釋:在 scala 程式設計中,註釋的方式和 java 中註釋方式一樣,原則:少而精 
 
3、關鍵字:關注新關鍵字:yield, match, object, def, implicit, trait, sealed, var/val 

3.5、流程控制--條件表示式 if 
Scala 的的條件表示式比較簡潔,例如: 

package com.mazh.scala.core 
 
/** 
  * 作者: 李濤: https://blog.csdn.net/qq_42244689 
  */ 
object ConditionDemo { 
  def main(args: Array[String]) { 
    val x = 1 
    // 判斷 x
的值,將結果賦給 y 
    val y = if (x > 0) 1 else -1 
    // 列印 y
的值 
    println(y) 
 
    // 支援混合型別表示式     val z = if (x > 1) 1 else "error" 
    // 列印 z
的值 
    println(z) 
 
    // 如果缺失 else ,相當於 if (x > 2) 1 else () 
    val m = if (x > 2) 1 
 println(m) 
 
    // 在 scala中每個表示式都有值, scala中有個 Unit類,寫做 (), 相當於 Java中的 void 
    val n = if (x > 2) 1 else () 
    println(n) 
 
    //if
和 else if 
    val k = if (x < 0) 0 
    else if (x >= 1) 1 else -1 
    println(k) 
  } 
} 

總結:

1)if 條件表示式它是有返回值的,返回值是多個分支的返回結果的共同父類

2)返回值會根據條件表示式的情況會進行自動的資料型別的推斷(返回的是多個分支的共 同父類) 

 

3.6、塊表示式 

package com.mazh.scala.core 
 
/** 
  * 作者: 李濤: https://blog.csdn.net/qq_42246689
  */ 
object BlockExpresstionDemo { 
  def main(args: Array[String]) { 
    val x = 0 
    // 在 scala
中 {} 中課包含一系列表示式, 塊中最後一個表示式的值就是塊的值 
    // 下面就是一個塊表示式     val result = { 
      if (x < 0){ 
        -1 
      } else if(x >= 1) { 
        1 
      } else { 
        "error" 
      } 
    } 
    //result
的值就是塊表示式的結果 
    println(result) 
  } 
} 

總結:就算是賦值表示式,也是有返回值的。是空,是 Unit 

 

3.7、流程控制--迴圈 for 和 while 
在 scala 中有 for 迴圈和 while 迴圈,用 for 迴圈比較多

for 迴圈語法結構:for (i <- 表示式/陣列/集合) 

package com.mazh.scala.core 
 
/** 
  * 作者: 李濤: https://blog.csdn.net/qq_42246689 
  */ 
object ForDemo { 
  def main(args: Array[String]) { 
    //for(i <- 表示式 ), 表示式 1 to 10
返回一個 Range (區間) 
    // 每次迴圈將區間中的一個值賦給 i 
    for (i <- 1 to 10) 
      println(i) 
 
    //for(i <- 陣列 ) 
    val arr = Array("a", "b", "c") 
    for (i <- arr) 
      println(i) 
 
    // 倒序列印     for (str <- arr.reverse){ 
      println(str) 
    } 
 
    // 使用陣列下標的方式進行列印     for (i <- 0 to arr.length - 1){ 
      println(arr(i)) 
    } 
 
    for (i <- 0 until arr.length) 
      println(arr(i)) 
 
    println("-----------------") 
    for (i <- 0 until (arr.length, 2)) 
      println(arr(i)) 
    // 高階 for迴圈 
    // 每個生成器都可以帶一個條件,注意: if前面沒有分號 
    for(i <- 1 to 3; j <- 1 to 3 if i == j) 
      println((10 * i + j) + " ") 
    println() 
 
    //for推導式:如果 for迴圈的迴圈體以 yield開始,則該迴圈會構建出一個集合 
    // 每次迭代生成集合中的一個值     val v = for (i <- 1 to 10) yield i * 10 
    println(v) 
 
  } 
}

總結:

1、在 scala 裡面沒有運算子,都有的符號其實都是方法。

2、在 scala 裡面沒有 ++  -- 的用法

3、for( i  <- 表示式/陣列/集合)

4、在 for 迴圈裡面我們是可以新增 if 表示式

5、有兩個特殊表示式需要了解:    To    1 to 3     1 2 3    To    1 to (3,2)  1 3    Until  1 until 3   12

6、如果在使用 for 迴圈的時候,for 迴圈的時候我們需要獲取,我們可以是使用 yield 關鍵字 
 
While 迴圈測試例子:

package com.mazh.scala.core 
 
/** 
  * 作者: 李濤: https://blog.csdn.net/qq_42246689
  */ 
object WhileDemo { 
  def main(args: Array[String]) { 
    var n = 10; 
    while (n > 0) { 
      println(n) 
      n -= 1 
    } 
  } 
}

總結:

1)while 使用跟 java 一模一樣

2)注意點:在 scala 裡面不支援 i++  i-- 等操作統一寫成 i+=1  i-=1 v

 

3.8、方法和函式 

Scala 中的+ - * / %等操作符的作用與 Java 一樣,位操作符 & | ^ >> <<也一樣。

只是有一點特別的:這些操作符實際上是方法。

例如: a + b 是如下方法呼叫的簡寫: a.+(b) a 方法 b 可以寫成 a.方法(b) 
3.8.1、定義方法 

方法的返回值型別可以不寫,編譯器可以自動推斷出來,但是對於遞迴函式,必須指定返 回型別 注意:函式體應該改成叫方法體!!!如果不寫等號,代表沒有返回值。 

3.8.2、定義函式 

函式的意義:表示接受兩個 Int 型別的變數,然後做累加。 經過 scala 的自動型別推斷得知,最後返回的結果資料的型別也是 Int。 Function2 中 2 表示這個函式接收的引數個數是 2 個。 

3.8.3、方法和函式的區別 
1、函式可以作為引數傳遞給方法,也就是說函式可以作為方法的引數

在函數語言程式設計語言中,函式是“頭等公民”,它可以像任何其他資料型別一樣被傳遞和操作 案例:首先定義一個方法,再定義一個函式,然後將函式傳遞到方法裡面 
 

2、函式可以作為方法的引數,但是也可以作為函式的引數,例如: 

3、方法也可以作為方法的引數。在需要傳入函式作為引數的位置上傳入一個方法的話,那 麼這個方法會被自動的轉換為函式作為引數,也可以通過“_”把方法轉換為引數 
 
4、方法也可以作為函式的引數。其實,原理就是方法會被自動轉換為函式,所以也就是傳 入一個函式到一個函式作為引數。 
 

package com.aura.mazh.day1.core 
 
/** 
  * 作者: 李濤: https://blog.csdn.net/qq_42246689 
  */ 
object MethodAndFunctionDemo { 
  // 定義一個方法   // 方法 m2 引數要求是一個函式,函式的引數必須是兩個 Int
型別 
  // 返回值型別也是 Int
型別 
  def m1(f: (Int, Int) => Int) : Int = f(2, 6) 
// 定義一個計算資料不被寫死的方法   def m2(f: (Int, Int) => Int, x:Int, y:Int) : Int = f(x, y) 
 
  // 定義一個需要兩個 Int型別引數的方法 
  def m3(x:Int, y:Int):Int = x + y 
 
  // 定義一個函式 f1 ,引數是兩個 Int型別,返回值是一個 Int型別 
  val f1 = (x: Int, y: Int) => x + y 
  // 再定義一個函式 f2 
  val f2 = (m: Int, n: Int) => m * n 
 
  //main方法 
  def main(args: Array[String]) { 
 
    // 呼叫 m1方法,並傳入 f1函式 
    val r1 = m1(f1) 
    println(r1) 
 
    // 呼叫 m1方法,並傳入 f2函式 
    val r2 = m1(f2) 
    println(r2) 
 
    // 呼叫 m2方法, 傳入 f1函式 
    val result1 = m2(f1, 2, 4) 
    println(result1) 
 
    // 呼叫 m2方法,傳入 f2函式 
    val result2 = m2(f2, 2, 4) 
    println(result2) 
 
    // 呼叫 m2方法, 傳入 mm方法作為引數 
    println(m2(m3, 2, 4)) 
  }
}

3.8.4、將方法轉換成函式使用 

 

3.9、Scala 函數語言程式設計特點 S
(1)高階函式(Higher-order functions)

(2)閉包(closures)

(3)模式匹配(Pattern matching)

(4)單一賦值(Single assignment)

(5)延遲計算(Lazy evaluation)

(6)型別推導(Type inference)

(7)尾部呼叫優化(Tail call optimization)

(8)型別推導(Type inference)