為了用spark,先學下scala。
參考教程:http://meetfp.com/zh/scala-basic
doc查詢:http://docs.scala-lang.org
其它資料:http://scalachina.com/node/16 http://blog.csdn.net/mapdigit/article/details/21878083
特點:
- Scala是一種純面向對象的語言,一切都是對象:將原始類型和類統一起來,同時也將函數和操作符統一起來。
- Scala又是函數式語言,這體現在,函數在Scala中也是一種對象,並且能非常自然的使用高階函數。
- Scala是靜態類型的語言,但是由於它強大的類型推斷,實際需要指定類型的地方並不多。在擁有靜態語言和編譯型語言的安全高效的優勢的同時,Scala使用起來像Ruby,Python等靜態語言一樣方便,靈活,簡潔。
0.環境配置:
先略過,用的在線編譯。
- 行結束默認為語句結束,如果你想要在一行內輸入多個語句,則使用分號。
- 跨行的語句,你得使用括號,或者將操作符放在未結束的行尾,它將被當作語句位結束的標志。
object HelloWorld { def main(args: Array[String]) { println("Hello, world!") } }
I.變量函數
1.變量: var ,val—— immutable
- Scala的變量分兩種,var和val。var,即variable,類似於我們在Java等其他語言中接觸到的變量,而val,是value,類似於我們在其他語言中用到的不可重新賦值的常量,或者final變量。Scala非常強調不可變(immutable)的概念。
- Scala編譯器通過類型推斷(Type Inference)可推斷出數據類型,也可顯式指定變量類型,類型在變量名稱后,用冒號(:)分隔。
var a: Int =5
2.函數(function),過程(procedure)
- 由上面代碼可以看到,函數定義以def開始,然后是函數名稱,接下來,小括號內是函數的參數列表,參數之間逗號分隔。與Java或C不同的是,參數的類型出現在參數名之后,與參數名稱冒號分隔。 函數的類型(也就是返回值的類型)在參數列表之后,也用冒號分隔。在函數類型之后,是等號“=”,然后才是大括號包圍起來的函數體。函數返回類型可以省略,因為編譯器可以推斷出來。不過,為了代碼的可讀性,應該盡量注明返回類型,只有在代碼非常簡短,能一眼看出返回類型的情況下,可省略它。
def add(x: Int, y: Int) : Int = { x + y } println("2 + 3 = " + add(2,3))
- 過程的目的是為了某種“副作用”,而不是為了得到計算結果。如上所述,過程只是一種特殊的函數,具體來說,是沒有返回值,或者說返回類型為Unit的函數。
def sayHiTo(name: String) { println("Hi, " + name) } sayHiTo("Nini")
PS:(1)命名參數可讓你在傳參時指定參數名,這樣,參數的位置將不再重要。
addUser(name = "Tim", phone = "702-201-2345", age = 33)
(2)默認參數,同其它語言。
(3)重復參數,類型后面有一個'*',這表示這個參數可以重復不定次數,包括0次。當參數個數不是0時,重復參數在內部其實是一個Array。使用時跟Array差不多,只是,調用時不能傳遞直接Array進來。如果需要傳遞整個Array(或者別的類型的序列)的話,有一個變通方法,那就是,加一個'_*'符號,該符號與參數之間用逗號分隔,比如log(array: _*)
。
def log(msgs: String*) = { println(msgs.getClass.getName) println(msgs.mkString(",")) } log() log("one","two","three") val array = Array("one","two","three") //log(array) //above line wouldn't compile, type mismatch, expected String log(array: _*)
II.操作符
- Scala沒有操作符,也沒有通常意義上的表達式。其實是方法(函數),叫做操作符記法。如 1+2 與 1.+(2)
- 能做前綴的操作符很少,只有四個:+,-,!,~。另外,前綴表達式有一些特別,它們的方法需要把對應的操作符前加上unary_,比如
unary_!
,或者unary_-
。 - 由於操作符本質上就是方法,你可以跟方法重載一樣重載操作符。
- 常用操作符及優先性類似c++,不詳述了。
* / % + - : = ! < > & ^ |
- 以`:`結尾的操作符是右結合的,其他操作符都是左結合的。
III.基本類型
在Scala中,基本類型也是class,比如,Int類型,來自scala.Int,每一個數字,都是scala.Int的一個實例。裝箱(boxing)和拆箱(unboxing)操作是透明的,程序員不需要關心(實際上,這是由定義在Predef中的隱式轉換完成的)。
1.數值類型
- Boolean: true 或者 false
- Byte: 8位, 有符號(2-7 ~ 27 - 1)
- Short: 16位, 有符號 (2-15 ~ 215 - 1)
- Int: 32位, 有符號 (2-31 ~ 231 - 1)
- Long: 64位, 有符號 (2-63 ~ 263 - 1)
- Char: 16位, 無符號 (0 ~ 216 - 1)
- Float: 32位, 單精度浮點數
- Double: 64位, 雙精度浮點數
每一個基本類型都有一個相對應的富包裝類。 基本類型,在必要的時候通過隱式轉換轉換為對應的富包裝類,從而可調用富包裝類提供的方法。
//RichInt val n1 = 2 max 3 println("2 max 3 = " + n1) val n2 = -1.abs println("-1.abs = " + n2) val n3 = 1 to 5 println("1 to 5 = " + n3) val n4 = 1.isValidChar println("1.isValidChar = " + n4) val n5 = -1.isValidChar println("-1.isValidChar = " + n5)
2.Scala里的String是直接借用了Java的String。不過,由於String實際是一系列Char的不可變的集合,Scala中大部分針對集合的操作,都可以用於String,具體來說,String的這些方法存在於類scala.collection.immutable.StringOps中。 由於String在需要時能隱式轉換為StringOps,因此不需要任何額外的轉換,String就可以使用這些方法。
val r3 = str.filter( _ != 'l') //"Heo" println("\"Hello\".filter( _ != 'l') = " + r3)
與Java或C#一樣,String是不可變的,對String進行操作,會得到新的String實例。因此在需要頻繁操作String的情況下,請使用StringBuilder。
val builder = new StringBuilder builder.append("Hello") builder.append(", world") builder += '!' builder.insert(0,"Me: ") println(builder) //Me: Hello, world!
3.字面常量:同java。XML擴展。函數常量。
val fun = new Function2[Int, Int, Int] { def apply(x: Int, y: Int): Int = x + y } val result = fun(2,4) println("Result = " + result) result
4.Scala中,所有的值都是類對象,而所有的類,包括值類型,都最終繼承自一個統一的根類型Any。統一類型,是Scala的又一大特點。更特別的是,Scala中還定義了幾個底層類(Bottom Class),比如Null和Nothing。
- Null是所有引用類型的子類型,而Nothing是所有類型的子類型。Null類只有一個實例對象,null,類似於Java中的null引用。null可以賦值給任意引用類型,但是不能賦值給值類型。
- Nothing,可以作為沒有正常返回值的方法的返回類型,非常直觀的告訴你這個方法不會正常返回,而且由於Nothing是其他任意類型的子類,他還能跟要求返回值的方法兼容。
- Unit類型用來標識過程,也就是沒有明確返回值的函數。 由此可見,Unit類似於Java里的void。Unit只有一個實例,
()
,這個實例也沒有實質的意義。