Scala基礎(chǔ)
Spark的原生語言是Scala,因此入門一下Scala是學(xué)習(xí)Spark的第一步,下面就快速入門一下待错,爭取不花太多的時間。之后的簡書中還會有Scala進階烈评,交代一些其他特性火俄。這篇Scala基礎(chǔ)應(yīng)該可以暫時應(yīng)付之后Spark的學(xué)習(xí)。
- Scala運行在JVM上
- Scala是純面向?qū)ο蟮恼Z言
- Scala是函數(shù)式編程語言
- Scala是靜態(tài)類型語言
1. HelloWorld
object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello, world!")
}
}
2. 交互式編程與腳本形式
交互式編程進入方式有兩種础倍,terminal中輸入scala
,或者輸入sbt
再輸入console
腳本形式則類似Java的編譯形式
$ scalac HelloWorld.scala
$ scala HelloWorld.scala
scalac編譯生成.class文件胎挎,注意可以跳過這一步沟启,直接使用scala來執(zhí)行
3. Scala包
定義包
package com.runoob
class HelloWorld
第二種定義包的方法,可以一個文件中定義多個包
package com.runoob {
class HelloWorld
}
源文件的目錄和包之間并沒有強制的關(guān)聯(lián)關(guān)系犹菇。你不需要將Employee.scala放在com/horstmann/impatient目錄當(dāng)中
package com {
package horstmann {
package impatient {
class Manager
......
}
}
}
引用包
import com.runoob.HelloWorld
import java.awt._ //引入包內(nèi)所有成員
注意scala中類和對象一般用大寫字母開頭
4. Scala變量與數(shù)據(jù)類型
數(shù)據(jù)類型
只羅列幾個特殊的德迹,注意所有的數(shù)據(jù)類型都是對象
- Byte, Short, Int(默認(rèn)), Long, Float, Double(默認(rèn)), Char, String
- Unit 表示無值,和其他語言中void等同揭芍。用作不返回任何結(jié)果的方法的結(jié)果類型胳搞。Unit只有一個實例值,寫成()称杨。
- Null null 或空引用
- Nothing Nothing類型在Scala的類層級的最低端肌毅;它是任何其他類型的子類型。
- Any Any是所有其他類的超類
- AnyRef AnyRef類是Scala里所有引用類(reference class)的基類
變量和常量
在 Scala 中姑原,使用關(guān)鍵詞 "var" 聲明變量悬而,使用關(guān)鍵詞 "val" 聲明常量
var myVar: String = "Foo"
var myVar2: Int //變量聲明不一定要初始值
val myVal: String = "Too" //常量不能修改
var myVar = 10; //常量和變量的聲明不一定要指明數(shù)據(jù)類型,編譯器會自己推斷
val myVal = "Hello, Scala!";
還可以聲明一個元組锭汛,變量常量都可以
scala> val pa = (40,"Foo")
pa: (Int, String) = (40,Foo)
5. Scala訪問修飾符
Scala訪問權(quán)限
- private:僅在包含了成員定義的類或?qū)ο髢?nèi)部可見笨奠。Java中允許這兩種訪問袭蝗,因為它允許外部類訪問內(nèi)部類的私有成員。
class Outer{
class Inner{
private def f(){println("f")}
class InnerMost{
f() // 正確
}
}
(new Inner).f() //錯誤
}
- protected:只允許保護成員在定義了該成員的的類的子類中被訪問般婆。而在java中到腥,用protected關(guān)鍵字修飾的成員,除了定義了該成員的類的子類可以訪問蔚袍,同一個包里的其他類也可以進行訪問乡范。
package p{
class Super{
protected def f() {println("f")}
}
class Sub extends Super{
f()
}
class Other{
(new Super).f() //錯誤
}
}
- public:Scala中,如果沒有指定任何的修飾符页响,則默認(rèn)為 public篓足。這樣的成員在任何地方都可以被訪問。
JAVA的訪問權(quán)限表
public--都可訪問(公有)
protected--包內(nèi)和子類可訪問(保護)
不寫(default)--包內(nèi)可訪問 (默認(rèn))
private--類內(nèi)可訪問(私有)
作用域保護
private[x]
或 protected[x]
這里的x指代某個所屬的包闰蚕、類或單例對象栈拖。如果寫成private[x],讀作"這個成員除了對[…]中的類或[…]中的包中的類及它們的伴生對像可見外,對其它所有類都是private没陡。
6. 運算符涩哟,條件,循環(huán)
和JAVA基本相同盼玄,舉幾個for循環(huán)使用的例子
<-表示為變量賦值贴彼,to表示包含后面的值
for( a <- 1 to 10){
println( "Value of a: " + a );
}
until表示不包含后面的值
for( a <- 1 until 10){
println( "Value of a: " + a );
}
在 for 循環(huán) 中你可以使用分號 (;) 來設(shè)置多個區(qū)間,它將迭代給定區(qū)間所有的可能值埃儿。
for( a <- 1 to 3; b <- 1 to 3){
println( "Value of a: " + a );
println( "Value of b: " + b );
}
for 循環(huán)會迭代所有集合的元素
val numList = List(1,2,3,4,5,6);
for( a <- numList ){
println( "Value of a: " + a );
}
for循環(huán)還可以加入條件過濾
val numList = List(1,2,3,4,5,6,7,8,9,10);
// 下面的代碼會輸出1,2,4,5,6,7
for( a <- numList
if a != 3; if a < 8 ){
println( "Value of a: " + a );
}
利用yield來產(chǎn)生集合器仗,和python不一樣的
val numList = List(1,2,3,4,5,6,7,8,9,10);
// 下面的代碼會輸出1,2,4,5,6,7
var retVal = for( a <- numList
if a != 3; if a < 8 )yield a
retVal: List[Int] = List(1, 2, 4, 5, 6, 7)
7. 函數(shù)
聲明
def functionName ([參數(shù)列表]) : [return type]
定義
def functionName ([參數(shù)列表]) : [return type] = {
function body
return [expr]
}
如果函數(shù)沒有返回值,可以返回為 Unit童番,這個類似于 Java 的 void
例子
object Test {
def main(args: Array[String]) {
println("Hello\tWorld\n\n")
println("3 + 4 = " + add(3, 4))
}
def add(a: Int, b: Int): Int = {
var sum: Int = a + b
return sum
}
}
8. 函數(shù)高級特性
傳名調(diào)用
傳名調(diào)用(Call-by-name):參數(shù)傳入時精钮,不事先計算,而是將表達(dá)式子代入其中
傳入?yún)?shù)時要用=>
object Test {
def main(args: Array[String]) {
delayed(time());
}
def time() = {
println("獲取時間剃斧,單位為納秒")
System.nanoTime
}
def delayed( t: => Long ) = {
println("在 delayed 方法內(nèi)")
println("參數(shù): " + t)
t
}
}
這個時候轨香,相當(dāng)于函數(shù)中的每個t都編程time(),所以輸出會變成
在 delayed 方法內(nèi)
獲取時間幼东,單位為納秒
參數(shù): 241550840475831
獲取時間臂容,單位為納秒
可變參數(shù)
Scala 允許你指明函數(shù)的最后一個參數(shù)可以是重復(fù)的,即我們不需要指定函數(shù)參數(shù)的個數(shù)根蟹,可以向函數(shù)傳入可變長度參數(shù)列表脓杉。
Scala 通過在參數(shù)的類型之后放一個星號來設(shè)置可變參數(shù)(可重復(fù)的參數(shù))。
object Test {
def main(args: Array[String]) {
printStrings("Runoob", "Scala", "Python");
}
def printStrings( args:String* ) = {
var i : Int = 0;
for( arg <- args ){
println("Arg value[" + i + "] = " + arg );
i = i + 1;
}
}
}
高階函數(shù)
高階函數(shù)(Higher-Order Function)就是操作其他函數(shù)的函數(shù)简逮。
object Test {
def main(args: Array[String]) {
println( apply( layout, 10) )
}
// 函數(shù) f 和 值 v 作為參數(shù)丽已,而函數(shù) f 又調(diào)用了參數(shù) v
def apply(f: Int => String, v: Int) = f(v)
def layout[A](x: A) = "[" + x.toString() + "]"
}
偏應(yīng)用函數(shù)
實際上就是固定函數(shù)的某些參數(shù)生成新的函數(shù),使用下劃線(_)替換缺失的參數(shù)列表
import java.util.Date
object Test {
def main(args: Array[String]) {
val date = new Date
val logWithDateBound = log(date, _ : String) //logWithDateBound就變成函數(shù)了
logWithDateBound("message1" )
Thread.sleep(1000)
logWithDateBound("message2" )
Thread.sleep(1000)
logWithDateBound("message3" )
}
def log(date: Date, message: String) = {
println(date + "----" + message)
}
}
匿名函數(shù)
相當(dāng)于python中的lambda
var inc = (x:Int) => x+1
var mul = (x: Int, y: Int) => x*y
var userDir = () => { System.getProperty("user.dir") }
//調(diào)用
var x = inc(7)-1
println(mul(3, 4))
println(userDir())
函數(shù)柯里化(Currying)
def add(x:Int)(y:Int) = x + y
// 調(diào)用
var a = add(1)(2)
add(1)(2) 實際上是依次調(diào)用兩個普通函數(shù)(非柯里化函數(shù))买决,第一次調(diào)用使用一個參數(shù) x沛婴,返回一個函數(shù)類型的值吼畏,第二次使用參數(shù)y調(diào)用這個函數(shù)類型的值。