Hadoop(二十三)scala基礎(chǔ)

1.1. 什么是Scala

Scala是一種多范式的編程語言,其設(shè)計的初衷是要集成面向?qū)ο缶幊毯秃瘮?shù)式編程的各種特性。Scala運行于Java平臺(Java虛擬機),并兼容現(xiàn)有的Java程序。[圖片上傳失敗...(image-c23538-1527488548129)]

1.2. 為什么要學(xué)Scala

1.優(yōu)雅:這是框架設(shè)計師第一個要考慮的問題,框架的用戶是應(yīng)用開發(fā)程序員,API是否優(yōu)雅直接影響用戶體驗。

2.速度快:Scala語言表達能力強,一行代碼抵得上Java多行,開發(fā)速度快;Scala是靜態(tài)編譯的,所以和JRuby,Groovy比起來速度會快很多。

  1. 能融合到Hadoop生態(tài)圈:Hadoop現(xiàn)在是大數(shù)據(jù)事實標準,Spark并不是要取代Hadoop,而是要完善Hadoop生態(tài)。JVM語言大部分可能會想到Java,但Java做出來的API太丑,或者想實現(xiàn)一個優(yōu)雅的API太費勁。

[圖片上傳失敗...(image-b141d4-1527488548129)]

2. Scala編譯器安裝

2.1. 安裝JDK

因為Scala是運行在JVM平臺上的,所以安裝Scala之前要安裝JDK

2.2. 安裝Scala

2.2.1. Windows安裝Scala編譯器

訪問Scala官網(wǎng)http://www.scala-lang.org/下載Scala編譯器安裝包,目前最新版本是2.12.x,但是目前大多數(shù)的框架都是用2.10.x編寫開發(fā)的,所以這里推薦2.10.x版本,下載scala-2.10.6.msi后點擊下一步就可以了

2.2.2. Linux安裝Scala編譯器

下載Scala地址http://downloads.typesafe.com/scala/2.10.6/scala-2.10.6.tgz然后解壓Scala到指定目錄

tar -zxvf scala-2.10.6.tgz -C /usr/java

配置環(huán)境變量,將scala加入到PATH中

vi /etc/profile

export JAVA_HOME=/usr/java/jdk1.7.0_45

export PATH=$PATH:$JAVA_HOME/bin:/usr/java/scala-2.10.6/bin

2.2.3. Scala開發(fā)工具安裝

目前Scala的開發(fā)工具主要有兩種:Eclipse和IDEA,這兩個開發(fā)工具都有相應(yīng)的Scala插件,如果使用Eclipse,直接到Scala官網(wǎng)下載即可http://scala-ide.org/download/sdk.html

由于IDEA的Scala插件更優(yōu)秀,大多數(shù)Scala程序員都選擇IDEA,可以到http://www.jetbrains.com/idea/download/下載社區(qū)免費版,點擊下一步安裝即可,安裝時如果有網(wǎng)絡(luò)可以選擇在線安裝Scala插件。這里我們使用離線安裝Scala插件:

1.安裝IDEA,點擊下一步即可。由于我們離線安裝插件,所以點擊Skip All and Set Defaul

2.下載IEDA的scala插件,地址http://plugins.jetbrains.com/?idea_ce

[圖片上傳失敗...(image-395c8d-1527488548129)]

3.安裝Scala插件:Configure -> Plugins -> Install plugin from disk -> 選擇Scala插件 -> OK -> 重啟IDEA

[圖片上傳失敗...(image-e87daf-1527488548129)]

[圖片上傳失敗...(image-fe195c-1527488548129)]

[圖片上傳失敗...(image-1dd0dd-1527488548129)]

[圖片上傳失敗...(image-b0367d-1527488548129)]

3. Scala基礎(chǔ)

3.1. 聲明變量

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*

  • Created by ZX on 2015/11/6.

/ object VariableDemo { def main(args: Array[String]) { //使用val定義的變量值是不可變的,相當于java里用final修飾的變量 val i = 1 //使用var定義的變量是可變得,在Scala中鼓勵使用val var s = "hello" //Scala編譯器會自動推斷變量的類型,必要的時候可以指定類型</pre>

<pre style="mso-pagination:widow-orphan;background:white"> //變量名在前,類型在后 val str: String = "itcast" }

}</pre>

|

3.2. 常用類型

Scala和Java一樣,有7種數(shù)值類型Byte、Char、Short、Int、Long、Float和Double(無包裝類型)和一個Boolean類型

3.3. 條件表達式

Scala的的條件表達式比較簡潔,例如:

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*

  • Created by ZX on 2015/11/7.

/ object ConditionDemo { def main(args: Array[String]) { val x = 1 //判斷x的值,將結(jié)果賦給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)

}

}</pre>

|

3.4. 塊表達式

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*

  • Created by ZX on 2015/11/7.

/ object BlockExpressionDemo { def main(args: Array[String]) { val x = 0 //在scala中{}中課包含一系列表達式,塊中最后一個表達式的值就是塊的值 //下面就是一個塊表達式 val result = { if (x < 0){

-1 } else if(x >= 1) { 1 } else { "error" }

} //result的值就是塊表達式的結(jié)果 println(result)

}

}</pre>

|

3.5. 循環(huán)

在scala中有for循環(huán)和while循環(huán),用for循環(huán)比較多

<pre style="mso-pagination:widow-orphan;background:white">for循環(huán)語法結(jié)構(gòu):for (i <- 表達式/數(shù)組/集合)</pre>

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*

  • Created by ZX on 2015/11/7.

/ object ForDemo { def main(args: Array[String]) { //for(i <- 表達式),表達式1 to 10返回一個Range(區(qū)間)</pre>

<pre style="mso-pagination:widow-orphan;background:white"> //每次循環(huán)將區(qū)間中的一個值賦給i for (i <- 1 to 10)

println(i) //for(i <- 數(shù)組) val arr = Array("a", "b", "c") for (i <- arr)

println(i) //高級for循環(huán) //每個生成器都可以帶一個條件,注意:if前面沒有分號 for(i <- 1 to 3; j <- 1 to 3 if i != j)

print((10 * i + j) + " ")

println() //for推導(dǎo)式:如果for循環(huán)的循環(huán)體以yield開始,則該循環(huán)會構(gòu)建出一個集合</pre>

<pre style="mso-pagination:widow-orphan;background:white"> //每次迭代生成集合中的一個值 val v = for (i <- 1 to 10) yield i * 10 println(v)

}

}</pre>

|

3.6. 調(diào)用方法和函數(shù)

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

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

a + b

是如下方法調(diào)用的簡寫:

a.+(b)

a 方法 b可以寫成 a.方法(b)

3.7. 定義方法和函數(shù)

3.7.1. 定義方法

[圖片上傳失敗...(image-a6b603-1527488548129)]

方法的返回值類型可以不寫,編譯器可以自動推斷出來,但是對于遞歸函數(shù),必須指定返回類型

3.7.2. 定義函數(shù)

[圖片上傳失敗...(image-c00ef5-1527488548129)]

3.7.3. 方法和函數(shù)的區(qū)別

在函數(shù)式編程語言中,函數(shù)是“頭等公民”,它可以像任何其他數(shù)據(jù)類型一樣被傳遞和操作

案例:首先定義一個方法,再定義一個函數(shù),然后將函數(shù)傳遞到方法里面

[圖片上傳失敗...(image-d79b3a-1527488548129)]

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*

  • Created by ZX on 2015/11/11.

/ object MethodAndFunctionDemo { //定義一個方法 //方法m2參數(shù)要求是一個函數(shù),函數(shù)的參數(shù)必須是兩個Int類型</pre>

<pre style="mso-pagination:widow-orphan;background:white"> //返回值類型也是Int類型 def m1(f: (Int, Int) => Int) : Int = {

f(2, 6)

} //定義一個函數(shù)f1,參數(shù)是兩個Int類型,返回值是一個Int類型 val f1 = (x: Int, y: Int) => x + y //再定義一個函數(shù)f2 val f2 = (m: Int, n: Int) => m * n //main方法 def main(args: Array[String]) { //調(diào)用m1方法,并傳入f1函數(shù) val r1 = m1(f1)

println(r1) //調(diào)用m1方法,并傳入f2函數(shù) val r2 = m1(f2)

println(r2)

}

}</pre>

|

3.7.4. 將方法轉(zhuǎn)換成函數(shù)(神奇的下劃線)

[圖片上傳失敗...(image-ddfd28-1527488548129)]

4. 數(shù)組、映射、元組、集合

4.1. 數(shù)組

4.1.1. 定長數(shù)組和變長數(shù)組

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala import scala.collection.mutable.ArrayBuffer /*

  • Created by ZX on 2015/11/11.

/ object ArrayDemo { def main(args: Array[String]) { //初始化一個長度為8的定長數(shù)組,其所有元素均為0 val arr1 = new ArrayInt //直接打印定長數(shù)組,內(nèi)容為數(shù)組的hashcode值 println(arr1) //將數(shù)組轉(zhuǎn)換成數(shù)組緩沖,就可以看到原數(shù)組中的內(nèi)容了 //toBuffer會將數(shù)組轉(zhuǎn)換長數(shù)組緩沖 println(arr1.toBuffer) //注意:如果new,相當于調(diào)用了數(shù)組的apply方法,直接為數(shù)組賦值 //初始化一個長度為1的定長數(shù)組 val arr2 = ArrayInt

println(arr2.toBuffer) //定義一個長度為3的定長數(shù)組 val arr3 = Array("hadoop", "storm", "spark") //使用()來訪問元素 println(arr3(2)) *//////////////////////////////////////////////////

//變長數(shù)組(數(shù)組緩沖) //如果想使用數(shù)組緩沖,需要導(dǎo)入import scala.collection.mutable.ArrayBuffer包val ab = ArrayBufferInt //向數(shù)組緩沖的尾部追加一個元素 //+=尾部追加元素* ab += 1 //追加多個元素 ab += (2, 3, 4, 5) //追加一個數(shù)組++= ab ++= Array(6, 7) //追加一個數(shù)組緩沖 ab ++= ArrayBuffer(8,9) //*打印數(shù)組緩沖ab

//在數(shù)組某個位置插入元素用insert* ab.insert(0, -1, 0) //刪除數(shù)組某個位置的元素用remove ab.remove(8, 2)

println(ab)

}

}</pre>

|

4.1.2. 遍歷數(shù)組

1.增強for循環(huán)

2.好用的until會生成腳標,0 until 10 包含0不包含10

[圖片上傳失敗...(image-7d32da-1527488548119)]

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*

  • Created by ZX on 2015/11/12.

/ object ForArrayDemo { def main(args: Array[String]) { //初始化一個數(shù)組 val arr = Array(1,2,3,4,5,6,7,8) //增強for循環(huán) for(i <- arr)

println(i) //*好用的until會生成一個Range

//reverse是將前面生成的Range反轉(zhuǎn)* for(i <- (0 until arr.length).reverse)

println(arr(i))

}

}</pre>

|

4.1.3. 數(shù)組轉(zhuǎn)換

yield關(guān)鍵字將原始的數(shù)組進行轉(zhuǎn)換會產(chǎn)生一個新的數(shù)組,原始的數(shù)組不變

[圖片上傳失敗...(image-6a6e95-1527488548119)]

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*

  • Created by ZX on 2015/11/12.

/ object ArrayYieldDemo { def main(args: Array[String]) { //定義一個數(shù)組 val arr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9) //將偶數(shù)取出乘以10后再生成一個新的數(shù)組 val res = for (e <- arr if e % 2 == 0) yield e * 10 println(res.toBuffer) //更高級的寫法,用著更爽 //filter是過濾,接收一個返回值為boolean的函數(shù) //map相當于將數(shù)組中的每一個元素取出來,應(yīng)用傳進去的函數(shù) val r = arr.filter(_ % 2 == 0).map(_ * 10)

println(r.toBuffer)

}

}</pre>

|

4.1.4. 數(shù)組常用算法

在Scala中,數(shù)組上的某些方法對數(shù)組進行相應(yīng)的操作非常方便!

[圖片上傳失敗...(image-6ebce7-1527488548119)]

4.2. 映射

在Scala中,把哈希表這種數(shù)據(jù)結(jié)構(gòu)叫做映射

4.2.1. 構(gòu)建映射

[圖片上傳失敗...(image-3ef147-1527488548119)]

4.2.2. 獲取和修改映射中的值

[圖片上傳失敗...(image-1ff9aa-1527488548119)]

好用的getOrElse

[圖片上傳失敗...(image-903ef4-1527488548119)]

注意:在Scala中,有兩種Map,一個是immutable包下的Map,該Map中的內(nèi)容不可變;另一個是mutable包下的Map,該Map中的內(nèi)容可變

例子:

[圖片上傳失敗...(image-9de60c-1527488548119)]

注意:通常我們在創(chuàng)建一個集合是會用val這個關(guān)鍵字修飾一個變量(相當于java中的final),那么就意味著該變量的引用不可變,該引用中的內(nèi)容是不是可變,取決于這個引用指向的集合的類型

4.3. 元組

映射是K/V對偶的集合,對偶是元組的最簡單形式,元組可以裝著多個不同類型的值。

4.3.1. 創(chuàng)建元組

[圖片上傳失敗...(image-fae745-1527488548119)]

4.3.2. 獲取元組中的值

[圖片上傳失敗...(image-535291-1527488548119)]

4.3.3. 將對偶的集合轉(zhuǎn)換成映射

[圖片上傳失敗...(image-fee793-1527488548119)]

4.3.4. 拉鏈操作

zip命令可以將多個值綁定在一起

[圖片上傳失敗...(image-e37f23-1527488548119)]

注意:如果兩個數(shù)組的元素個數(shù)不一致,拉鏈操作后生成的數(shù)組的長度為較小的那個數(shù)組的元素個數(shù)

4.4. 集合

Scala的集合有三大類:序列Seq、集Set、映射Map,所有的集合都擴展自Iterable特質(zhì)

在Scala中集合有可變(mutable)和不可變(immutable)兩種類型,immutable類型的集合初始化后就不能改變了(注意與val修飾的變量進行區(qū)別)

4.4.1. 序列

不可變的序列 import scala.collection.immutable._

在Scala中列表要么為空(Nil表示空列表)要么是一個head元素加上一個tail列表。

9 :: List(5, 2) :: 操作符是將給定的頭和尾創(chuàng)建一個新的列表

注意::: 操作符是右結(jié)合的,如9 :: 5 :: 2 :: Nil相當于 9 :: (5 :: (2 :: Nil))

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.collect object ImmutListDemo { def main(args: Array[String]) { //創(chuàng)建一個不可變的集合 val lst1 = List(1,2,3) //將0插入到lst1的前面生成一個新的List val lst2 = 0 :: lst1 val lst3 = lst1.::(0) val lst4 = 0 +: lst1 val lst5 = lst1.+:(0) //將一個元素添加到lst1的后面產(chǎn)生一個新的集合 val lst6 = lst1 :+ 3 val lst0 = List(4,5,6) //將2個list合并成一個新的List val lst7 = lst1 ++ lst0 //將lst1插入到lst0前面生成一個新的集合 val lst8 = lst1 ++: lst0 //將lst0插入到lst1前面生成一個新的集合 val lst9 = lst1.:::(lst0)

println(lst9)

}

}</pre>

|

可變的序列 import scala.collection.mutable._

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.collect import scala.collection.mutable.ListBuffer object MutListDemo extends App{ //構(gòu)建一個可變列表,初始有3個元素1,2,3 val lst0 = ListBufferInt //創(chuàng)建一個空的可變列表 val lst1 = new ListBuffer[Int] //向lst1中追加元素,注意:沒有生成新的集合 lst1 += 4 lst1.append(5) //將lst1中的元素最近到lst0中, 注意:沒有生成新的集合 lst0 ++= lst1 //將lst0和lst1合并成一個新的ListBuffer 注意:生成了一個集合 val lst2= lst0 ++ lst1 //將元素追加到lst0的后面生成一個新的集合 val lst3 = lst0 :+ 5 }</pre>

|

4.5. Set

不可變的Set

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.collect import scala.collection.immutable.HashSet object ImmutSetDemo extends App{ val set1 = new HashSetInt //將元素和set1合并生成一個新的set,原有set不變 val set2 = set1 + 4 //set中元素不能重復(fù) val set3 = set1 ++ Set(5, 6, 7) val set0 = Set(1,3,4) ++ set1 println(set0.getClass)

}</pre>

|

可變的Set

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.collect import scala.collection.mutable object MutSetDemo extends App{ //創(chuàng)建一個可變的HashSet val set1 = new mutable.HashSetInt //向HashSet中添加元素 set1 += 2 //add等價于+= set1.add(4) set1 ++= Set(1,3,5)

println(set1) //刪除一個元素 set1 -= 5 set1.remove(2)

println(set1)

}</pre>

|

4.6. Map

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.collect import scala.collection.mutable object MutMapDemo extends App{ val map1 = new mutable.HashMapString, Int //向map中添加數(shù)據(jù) map1("spark") = 1 map1 += (("hadoop", 2)) map1.put("storm", 3)

println(map1) //從map中移除元素 map1 -= "spark" map1.remove("hadoop")

println(map1)

}</pre>

|

5. 類、對象、繼承、特質(zhì)

Scala的類與Java、C++的類比起來更簡潔,學(xué)完之后你會更愛Scala!!!

5.1. 類

5.1.1. 類的定義

|

<pre style="mso-pagination:widow-orphan;background:white">//在Scala中,類并不用聲明為public。</pre>

<pre style="mso-pagination:widow-orphan;background:white">//Scala源文件中可以包含多個類,所有這些類都具有公有可見性。 class Person { //用val修飾的變量是只讀屬性,有g(shù)etter但沒有setter</pre>

<pre style="mso-pagination:widow-orphan;background:white"> //(相當與Java中用final修飾的變量) val id = "9527" </pre>

<pre style="mso-pagination:widow-orphan;background:white">//用var修飾的變量既有g(shù)etter又有setter var age: Int = 18</pre>

<pre style="mso-pagination:widow-orphan;background:white">//類私有字段,只能在類的內(nèi)部使用private var name: String = "****唐伯虎" //對象私有字段,訪問權(quán)限更加嚴格的,Person類的方法只能訪問到當前對象的字段 private[this] val pet = "****小強"</pre>

<pre style="mso-pagination:widow-orphan;background:white">}</pre>

|

5.1.2. 構(gòu)造器

注意:主構(gòu)造器會執(zhí)行類定義中的所有語句

|

<pre style="mso-pagination:widow-orphan;background:white">/*

每個類都有主構(gòu)造器,主構(gòu)造器的參數(shù)直接放置類名后面,與類交織在一起 / class Student(val* name: String, val age: Int){ //主構(gòu)造器會執(zhí)行類定義中的所有語句 println("****執(zhí)行主構(gòu)造器") try {

println("****讀取文件") throw new IOException("io exception")

} catch { case e: NullPointerException => println("****打印異常Exception : " + e) case e: IOException => println("****打印異常Exception : " + e)

} finally {

println("****執(zhí)行finally部分")

} private var gender = "male" //用this關(guān)鍵字定義輔助構(gòu)造器 def this(name: String, age: Int, gender: String){ //每個輔助構(gòu)造器必須以主構(gòu)造器或其他的輔助構(gòu)造器的調(diào)用開始</pre>

<pre style="mso-pagination:widow-orphan;background:white"> this(name, age)

println("****執(zhí)行輔助構(gòu)造器") this.gender = gender

}

}</pre>

|

|

<pre style="mso-pagination:widow-orphan;background:white">/*

**構(gòu)造器參數(shù)可以不帶val或var,如果不帶val或var的參數(shù)至少被一個方法所使用,</pre>

<pre style="mso-pagination:widow-orphan;background:white"> ****那么它將會被提升為字段 /</pre>

<pre style="mso-pagination:widow-orphan;background:white">//在類名后面加private就變成了私有的 class Queen private(val name: String, prop: Array[String], private var age: Int = 18){

println(prop.size) //prop*被下面的方法使用后,prop就變成了不可變得對象私有字段,等同于private[this] val prop

//如果沒有被方法使用該參數(shù)將不被保存為字段,僅僅是一個可以被主構(gòu)造器中的代碼訪問的普通參數(shù)* def description = name + " is " + age + " years old with " + prop.toBuffer

} object Queen{ def main(args: Array[String]) {

//私有的構(gòu)造器,只有在其伴生對象中使用 val q = new Queen("hatano", Array("****蠟燭", "****皮鞭"), 20)

println(q.description())

}

}</pre>

|

5.2. 對象

5.2.1. 單例對象

在Scala中沒有靜態(tài)方法和靜態(tài)字段,但是可以使用object這個語法結(jié)構(gòu)來達到同樣的目的

1.存放工具方法和常量

2.高效共享單個不可變的實例

3.單例模式

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala import scala.collection.mutable.ArrayBuffer /*

  • Created by ZX on 2015/11/14.

/ object SingletonDemo { def main(args: Array[String]) { //單例對象,不需要new,用【類名.方法】調(diào)用對象中的方法 val session = SessionFactory.getSession() println(session)

}

} object SessionFactory{ //該部分相當于java中的靜態(tài)塊 var counts = 5 val sessions = new ArrayBufferSession while(counts > 0){ sessions += new Session counts -= 1 } //在object中的方法相當于java中的靜態(tài)方法 def getSession(): Session ={ sessions.remove(0)

}

} class Session{

}</pre>

|

5.2.2. 伴生對象

在Scala的類中,與類名相同的對象叫做伴生對象,類和伴生對象之間可以相互訪問私有的方法和屬性

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*

  • Created by ZX on 2015/11/14.

/ class Dog { val id = 1 private var name = "itcast" def printName(): Unit ={ //在Dog類中可以訪問伴生對象Dog的私有屬性 println(Dog.CONSTANT + name )

}

} /*

** 伴生對象 / object Dog { //伴生對象中的私有屬性* private val CONSTANT = "****汪汪汪 : " def main(args: Array[String]) { val p = new Dog //訪問私有的字段name p.name = "123" p.printName()

}

}</pre>

|

5.2.3. apply方法

通常我們會在類的伴生對象中定義apply方法,當遇到類名(參數(shù)1,...參數(shù)n)時apply方法會被調(diào)用

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala</pre>

<pre style="mso-pagination:widow-orphan;background:white"> /*

  • Created by ZX on 2015/11/14.

/ object ApplyDemo { def main(args: Array[String]) { //調(diào)用了Array伴生對象的apply方法 //def apply(x: Int, xs: Int): Array[Int]

//arr1中只有一個元素5* val arr1 = Array(5)

println(arr1.toBuffer) //new了一個長度為5的array,數(shù)組里面包含5個null var arr2 = new Array(5)

}

}</pre>

|

5.2.4. 應(yīng)用程序?qū)ο?/h3>

Scala程序都必須從一個對象的main方法開始,可以通過擴展App特質(zhì),不寫main方法。

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*

  • Created by ZX on 2015/11/14.

/ object AppObjectDemo extends App{ //不用寫main方法 println("I love you Scala")

}</pre>

|

5.3. 繼承

5.3.1. 擴展類

在Scala中擴展類的方式和Java一樣都是使用extends關(guān)鍵字

5.3.2. 重寫方法

在Scala中重寫一個非抽象的方法必須使用override修飾符

5.3.3. 類型檢查和轉(zhuǎn)換

|

Scala

|

Java

|
|

obj.isInstanceOf[C]

|

obj instanceof C

|
|

obj.asInstanceOf[C]

|

(C)obj

|
|

classOf[C]

|

C.class

|

5.3.4. 超類的構(gòu)造

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*

  • Created by ZX on 2015/11/10.

/ object ClazzDemo { def main(args: Array[String]) { *//val h = new Human

//println(h.fight)* }

} trait Flyable{ def fly(): Unit ={

println("I can fly")

} def fight(): String } abstract class Animal { def run(): Int val name: String } class Human extends Animal with Flyable{ val name = "abc" //打印幾次"ABC"? val t1,t2,(a, b, c) = {

println("ABC")

(1,2,3)

}

println(a)

println(t1._1) //在Scala中重寫一個非抽象方法必須用override修飾 override def fight(): String = { "fight with 棒子" } //在子類中重寫超類的抽象方法時,不需要使用override關(guān)鍵字,寫了也可以 def run(): Int = { 1 }

}</pre>

|

6. 模式匹配和樣例類

Scala有一個十分強大的模式匹配機制,可以應(yīng)用到很多場合:如switch語句、類型檢查等。

并且Scala還提供了樣例類,對模式匹配進行了優(yōu)化,可以快速進行匹配

6.1. 匹配字符串

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.cases import scala.util.Random object CaseDemo01 extends App{ val arr = Array("YoshizawaAkiho", "YuiHatano", "AoiSola") val name = arr(Random.nextInt(arr.length)) name match { case "YoshizawaAkiho" => println("****吉澤老師...") case "YuiHatano" => println("****波多老師...") case _ => println("****真不知道你們在說什么...")

}

}</pre>

|

6.2. 匹配類型

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.cases import scala.util.Random object CaseDemo01 extends App{ //val v = if(x >= 5) 1 else if(x < 2) 2.0 else "hello" val arr = Array("hello", 1, 2.0, CaseDemo) val v = arr(Random.nextInt(4))

println(v) v match { case x: Int => println("Int " + x) case y: Double if(y >= 0) => println("Double "+ y) case z: String => println("String " + z) case _ => throw new Exception("not match exception")

}

}</pre>

|

注意****:case y: Double if(y >= 0) => ...

模式匹配的時候還可以添加守衛(wèi)條件。如不符合守衛(wèi)條件,將掉入case _中

6.3. 匹配數(shù)組、元組

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.cases object CaseDemo03 extends App{ val arr = Array(1, 3, 5) arr match { case Array(1, x, y) => println(x + " " + y) case Array(0) => println("only 0") case Array(0, _) => println("0 ...") case _ => println("something else"*)

} val lst = List(3, -1) lst match { case 0 :: Nil => println("only 0") case x :: y :: Nil => println(s"x: $x y: $y") case 0 :: tail => println("0 ...") case _ => println("something else")

} val tup = (2, 3, 7) tup match { case (1, x, y) => println(s"1, $x , $y") case (_, z, 5) => println(z) case _ => println("else")

}

}</pre>

|

注意:在Scala中列表要么為空(Nil表示空列表)要么是一個head元素加上一個tail列表。

9 :: List(5, 2) :: 操作符是將給定的頭和尾創(chuàng)建一個新的列表

注意::: 操作符是右結(jié)合的,如9 :: 5 :: 2 :: Nil相當于 9 :: (5 :: (2 :: Nil))

6.4. 樣例類

在Scala中樣例類是一中特殊的類,可用于模式匹配。case class是多例的,后面要跟構(gòu)造參數(shù),case object是單例的

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.cases import scala.util.Random</pre>

<pre style="mso-pagination:widow-orphan;background:white">case class SubmitTask(id: String, name: String) case class HeartBeat(time: Long) case object CheckTimeOutTask object CaseDemo04 extends App{ val arr = Array(CheckTimeOutTask, HeartBeat(12333), SubmitTask("0001", "task-0001")) arr(Random.nextInt(arr.length)) match { case SubmitTask(id, name) => { println(s"$id, $name")//前面需要加上s, $id直接取id的值 } case HeartBeat(time) => {

println(time)

} case CheckTimeOutTask => {

println("check")

}

}

}</pre>

|

6.5. Option類型

在Scala中Option類型樣例類用來表示可能存在或也可能不存在的值(Option的子類有Some和None)。Some包裝了某個值,None表示沒有值

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.cases object OptionDemo { def main(args: Array[String]) { val map = Map("a" -> 1, "b" -> 2) val v = map.get("b") match { case Some(i) => i case None => 0 }

println(v) //更好的方式 val v1 = map.getOrElse("c", 0)

println(v1)

}

}</pre>

|

6.6. 偏函數(shù)

被包在花括號內(nèi)沒有match的一組case語句是一個偏函數(shù),它是PartialFunction[A, B]的一個實例,A代表參數(shù)類型,B代表返回類型,常用作輸入模式匹配

|

<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.cases object PartialFuncDemo { def func1: PartialFunction[String, Int] = { case "one" => 1 case "two" => 2 case _ => -1 }</pre>

<pre style="mso-pagination:widow-orphan;background:white"> def func2(num: String) : Int = num match { case "one" => 1 case "two" => 2 case _ => -1 }</pre>

<pre style="mso-pagination:widow-orphan;background:white"> def main(args: Array[String]) {

println(func1("one"))

println(func2("one"))

} }</pre>

|

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,996評論 2 374

推薦閱讀更多精彩內(nèi)容