0 Scala

0 Scala簡介

  • Scala是一門多範式的編程語言,一種相似java的編程語言 ,設計初衷是實現可伸縮的語言 、並集成面向對象編程和函數式編程的各類特性。

1 Scala環境

1.1 語言介紹

  • 他已經出生15年了,就像明星同樣,誰都不可能一開始就人氣爆棚粉絲無數,得慢慢混。php

  • 聽說這傢伙已經威脅到了Java的地位,我當時也是被這句話驚到,才毅然決然的認識了他。目前也正在努力學習中。估計到目前爲止國內沒有誰敢說已經精通Scala了。固然我猜想有絕大一部分人是爲了裝那個啥纔去學他的,說實話學了他確實能夠裝那個啥,畢竟很實用,並且學的人很少,學會的人更很少,能熟練運用的人更是少之又少。java

  • 你們確定都有個疑問,爲何Scala這麼受歡迎究竟是哪裏吸引了你們?撿重點說吧,篇幅不宜太多。linux

  • 身世介紹
    • Scala在2004年正式問世,他的爸爸是Martin Odersky,這位老頭同時也是Genenric Java的爸爸。神不神奇!Scala和Genenric Java竟然是親兄弟。不認識Genenric Java的小夥伴們,請自行百度吧。
    • Scala的全稱叫scalable,可伸縮的意思。說白了就是能夠簡單又能夠複雜。scala是個純正的面嚮對象語言,而且具有函數式編程特性,這也是他最吸引人的地方。另外還有個更更加吸引人的地方(至少對於我這枚Java汪來講)就是他是構建在jvm之上的,所以他能夠和Java進行無縫互操做,也就是說scala可使用Java的類庫,java有可使用scala程序。我覺的單憑這些就已經足夠能夠引發每一位Java程序員的興趣。
    • Scala之因此這麼受歡迎還有一個緣由,那就是Spark。專爲大規模數據處理而設計的快速通用的計算引擎,這正是spark的最好詮釋,關於spark的更多信息請百度。spark就是Scala編寫的,因此想了解spark的優越性能及應用就必須得學習Scala。

  Twitter相比你們都知道,其內部應用大量使用Scala。而在國內,使用Scala的公司還不是不少。但能夠預見,Scala時代即將到來。nginx

1.2 下載 Scala

  咱們能夠從 Scala 官網地址 http://www.scala-lang.org/downloads 下載 Scala 二進制包(頁面底部),本教程咱們將下載 2.10.5版本,以下圖所示:
    程序員

 

1.3 Windos安裝Scala (須要java環境)

解決windos必定會出的問題:安裝msi 提示250二、2503的錯誤代碼shell

  • 步驟一:
    • 一、按WIN+R,在運行框中輸入「gpedit.msc」 確認;
    • 二、打開本地策略組編輯器後依次展開 :「計算機配置」-》「管理模板」-》「windows組件」-》「windows installer」,並找到「始終以提高的權限進行安裝」;
    • 三、雙擊該選項,設置爲「已啓用」,並應用;
    • 四、最後咱們還要在本地策略組編輯器中的【用戶配置】中進行一樣的操做;
  • 步驟二:
    • 一、鼠標移到桌面左下角->右鍵(或者直接: WIN+X鍵),命令提示符(管理員);
    • 二、輸入:msiexec /package +‘msi文件路徑’(輸入的時候注意半角字符且路徑不能爲中文名)
    • 例如:C:\Windows\system32>msiexec /package "F:\micsoft\scala\scala-2.10.5.msi"」
  • 步驟三:配置環境變量

    設置 SCALA_HOME 變量:單擊新建,在變量名欄輸入:SCALA_HOME: 變量值一欄輸入:D:\Program Files(x86)\scala 也就是 Scala 的安裝目錄,根據我的狀況有所不一樣,若是安裝在 C 盤,將 D 改爲 C 便可。
  • 設置 Classpath 變量:找到找到系統變量下的"Classpath"如圖,單擊編輯,如沒有,則單擊"新建":
    • "變量名":ClassPath
    • "變量值":.;%SCALA_HOME%\bin;%SCALA_HOME%\lib\dt.jar;%SCALA_HOME%\lib\tools.jar;
  • 注意:"變量值"最前面的 .; 不要漏掉。最後單擊肯定便可。
  • 設置 Path 變量:找到系統變量下的"Path"如圖,單擊編輯。在"變量值"一欄的最前面添加以下的路徑: %SCALA_HOME%\bin;%SCALA_HOME%\jre\bin;
  • 注意:後面的分號 ; 不要漏掉。

1.4 linux 裝 Scala(須要java環境)

上傳scala的tar包到linux解壓

修改環境變量編程

vim ~/.bashrc

在文件的末尾加入:swift

export PATH="$PATH:/usr/local/src/scala-2.10.5/bin"


更新源後測試vim

source ~/.bashrc

  • Scala 中文亂碼解決
    • 在 Scala 2.11.7 版本上,Mac OS X 或 Linux 系統上編譯 Scala 代碼,若是出現中文,會出現亂碼的狀況。
    • 解決方案以下,分別編輯如下兩個執行腳本:
$ vim `which scala`  $ vim `which scalac` 

找到:windows

[ -n "$JAVA_OPTS" ] || JAVA_OPTS="-Xmx256M -Xms32M"

將其替換爲:

[ -n "$JAVA_OPTS" ] || JAVA_OPTS="-Xmx256M -Xms32M -Dfile.encoding=UTF-8"

從新編譯腳本,既能夠正常顯示中文。

1.5-idea配置scala

settings----plugins





/** * author Heaton * email tzy70416450@163.com * describe HelloWorld */ object HelloWorld { def main(args: Array[String]): Unit = { println("Hello World") } }

2 數據類型



  • Scala中定義變量使用var,定義常量使用val ,變量可變,常量不可變.變量和常量類型能夠省略不寫,會自動推斷。
    • val 不可變變量聲明 --> val 變動名 : 變量類型 = 值
    • var 可變變量聲明 --> var 變動名 : 變量類型 = 值
    • 通常狀況下咱們能夠不寫類型,這樣scala會自動斷定類型 --> val 變量名 = 值 | var 變量名 = 值
  • Scala中每行後面都會有分號自動推斷機制,不用顯式寫出「;」
  • 建議在Scala中命名使用駝峯命名法

  • 案例
object Test { def main(args: Array[String]): Unit = { val spark = "hello spark" //spark = "haha" --> 錯誤,不能給常量再賦值 println("常量" + spark) var helloHadoop = "hello hadoop" helloHadoop = "HELLO HADOOP" println("變量" + helloHadoop) //聲明一個數字 val num: Int = 55 println("聲明一個數字" + num) //聲明一個字符串 val word: String = "哈哈" println("聲明一個字符串" + word) //聲明一個浮點數 val fnum: Float = 33.33333333333333f println("聲明一個浮點數" + fnum) val dnum: Double = 33.33333333333333 println("聲明一個浮點數" + dnum) //聲明一個判斷類型 val flagt: Boolean = true val flagf: Boolean = false println("聲明一個判斷類型" + flagt) println("聲明一個判斷類型" + flagf) } }

測試

3 類和對象

  • Scala object至關於java中的單例,object中定義的全是靜態的,至關於java中的工具類,Object默認不能夠傳參,對象要傳參,使用apply方法。
  • Scala類中能夠傳參,傳參必定要指定類型,有了參數就有了默認了構造。類中的屬性默認有getter和setter方法
  • 類中重載構造時,構造中第一行必須先調用默認的構造 。def this(....){....}
  • Scala中當new class 時,類中除了方法不執行【除了構造方法】,其餘都執行。
  • 在同一個scala文件中,class名稱和Object名稱同樣時,這個類叫作個對象的伴生類,這個對象叫作這個類的伴生對象,他們之間能夠互相訪問私有變量。

  • 案例1
class Person(xname: String, xage: Int) { println("******* Person Class Start*******") private val name = xname var age = xage var gender = 'M' //觀察重載的構造器 def this(yname: String, yage: Int, ygender: Char) { this(yname, yage) this.gender = ygender } //觀察object的靜態性。直接調用其屬性 def sayName() = { println(name + " hello world... " + classAndObj.name) } println("******* Person Class End*******") } //觀察伴生對象可使用私有屬性 object Person{ val p = new Person("zhangsan", 20) println("伴生對象:"+p.name) } object classAndObj { println("******* classAndObj Object *******") val name = "wangwu" //object要傳參須要apply方法 def apply(i: Int) = { println("Score is " + i) } def apply(i: Int, s: String) = { println("name is " + s + ",score is " + i) } def main(args: Array[String]): Unit = { //object要傳參須要apply方法 classAndObj(1000) classAndObj(1000, "zhaoliu") val p = new Person("zhangsan", 20) //println(p.name)不能夠直接調用私有屬性 p.sayName() println(p.gender) val p1 = new Person("lisi", 18, 'F') p1.sayName() println(p1.gender) p1.age = 200 println(p1.age) } }

測試

  • 案例2
class Person { var name: String = _ //未賦值,會生成getter和setter方法 val age = 10 //只會生成getter方法 private[this] val gender = "male" //只能在定義裏使用,實例也不能調用 } object ObjTest { def main(args: Array[String]): Unit = { val p = new Person //括號可省略 p.name = "zhangsan" println(p.name + ":" + p.age) //println(p.gender) } }

測試

  • 案例3
class Person(val name : String,val age :Int) { //1.參數直接跟在類名後面的是主構造器 //2.主構造器中的參數最後會被編譯成字段 //3.主構造器在執行的時候會執行類中的全部語句 //4.假設參數聲明時不帶val和var,那麼至關於private[this]!!! println("這是一個主構造器") } object ObjTest { def main(args: Array[String]): Unit = { val p = new Person("zhangsan",15) println(p.name + ":" + p.age) } }

測試

  • 案例4
class Person(val name: String, val age: Int) { //1.參數直接跟在類名後面的是主構造器 //2.主構造器中的參數最後會被編譯成字段 //3.主構造器在執行的時候會執行類中的全部語句 //4.假設參數聲明時不帶val和var,那麼至關於private[this]!!! println("這是一個主構造器") var gender : String = _ //1. 附屬構造器,名稱是this //2. 每個附屬構造器必須首先調用已經存在的子構造器或者附屬構造器 def this(name: String, age: Int, gender: String) { this(name,age) this.gender = gender } } object ObjTest { def main(args: Array[String]): Unit = { val p = new Person("zhangsan", 15,"male") println(p.name + ":" + p.age + ":" + p.gender) } }

測試

  • 案例5
class Person(val name: String, val age: Int) { println("這是一個主構造器") } class Student(name: String, age: Int, val major: String) extends Person(name, age) { println("這是Person子類的一個主構造器") } object ObjTest { def main(args: Array[String]): Unit = { val s = new Student("zhangsan", 15, "Math") print(s.name + ":" + s.age + ":" + s.major) } }

測試

  • 案例6
class Person(val name: String, val age: Int) { println("這是一個主構造器") val school = "haha" def eat(): Unit ={ println("人吃飯") } } class Student(name: String, age: Int, val major: String) extends Person(name, age) { println("這是Person子類的一個主構造器") override val school = "xixi" override def toString = "override toString..." override def eat(): Unit ={ println("學生吃飯") } } object ObjTest { def main(args: Array[String]): Unit = { val s = new Student("zhangsan", 15, "Math") println(s.name + ":" + s.age + ":" + s.major) println(s.toString) println(s.school) s.eat() } }

測試

4 流程控制

4.1 if | else if | else -- 三元 -- for -- while -- do while

  • 案例
object Test { def main(args: Array[String]): Unit = { //if | else if | else val x = 3 if (x == 1) { println("x==1") } else if (x == 2) { println("x==2") } else { println("其餘狀況") } //三元 val num = if (x > 0) 1 else 0 println(num) println("*****") //while var (n, m) = (3, 0) while (n > 0) { m = m + n n = n - 1 } println(m) println("*****") //do while do{ println(m) }while(m<0) println("*****") //for 1-10 for (i <- 1 to 10) { print(i+"\t") } println() println("*****") //for 1-9 for (i <- 1 until 10) { print(i+"\t") } println() println("*****") //for 1-9 偶數 for (i <- 1 until 10 if i % 2 == 0) { print(i+"\t") } println() println("*****") //操做符函數寫法 println(1.to(10)) println(1.until(10)) println(1.until(10,2)) println("*****") //foreach val str = "abcd" str.foreach(x => print(x+"\t")) println() str.foreach(print(_)) println() str.foreach(print) } }

測試

4.2 match case

  • 案例
/** * Match 模式匹配 * 1.case _ 什麼都匹配不上匹配,放在最後 * 2.match 能夠匹配值還能夠匹配類型 * 3.匹配過程當中會有數值的轉換 * 4.從上往下匹配,匹配上以後會自動終止 * 5.模式匹配外部的「{..}」能夠省略 */ object Test extends App { def MatchTest(o: Any) = o match { case i: Int => println(s"type is Int ,value = $i") case 1 => println("value is 1") case d: Double => println(s"type is Double ,value = $d") case q if q.equals("abc") => println("value is abc") case s: String => println(s"type is String ,value = $s") case 'a' => println("value is a") case _ => { println("no match...") } } val tp = (1, 1.2, "abc", 'a', "xx", true) val iter: Iterator[Any] = tp.productIterator iter.foreach(MatchTest) }

測試

4.3 偏函數

  • 若是一個方法中沒有match 只有case,這個函數能夠定義成PartialFunction偏函數。偏函數定義時,不能使用括號傳參,默認定義PartialFunction中傳入一個值,匹配上了對應的case,返回一個值。
  • 案例
object Test extends App { def MyTest : PartialFunction[String,String] = { case "scala" =>{"scala"} case "hello"=>{"hello"} case _=> {"no match ..."} } println(MyTest("scala")) }

測試

4.4 樣例類(case classes)

  • 使用了case關鍵字的類定義就是樣例類(case classes),樣例類是種特殊的類。實現了類構造參數的getter方法(構造參數默認被聲明爲val),當構造參數是聲明爲var類型的,它將幫你實現setter和getter方法。
  • 樣例類默認幫你實現了toString,equals,copy和hashCode等方法。
  • 樣例類能夠new, 也能夠不用new
  • 案例1
case class Person1(name: String, age: Int) object Test extends App { val p1 = new Person1("zhangsan", 10) val p2 = Person1("lisi", 20) val p3 = Person1("wangwu", 30) val list = List(p1, p2, p3) list.foreach(x => { x match { case Person1("zhangsan", 10) => println("zhangsan") case Person1("lisi", 20) => println("lisi") case _ => println("no match") } }) }

測試

  • 案例2
class Code { } case class Book(name:String,author : String){ //構造器中的每個類型爲val //不用new就能夠產生對象(調用apply()方法) } object Test extends App { val hadoop = Book("Hadoop","zhangsan") hadoop match { case Book(name,author) =>println("this is a Book") case _ =>println("unknown") } }

測試

5 方法和函數

  • 案例1
object Test {
  //無返回值函數 def helloPrintName1(name: String): Unit = { println("無返回值函數: " + name) } //無返回值函數,: Unit 能夠省略 def helloPrintName2(name: String) = { println("無返回值函數: " + name) } //有返回值函數 def helloName1(name: String): String = { return "有返回值函數: " + name } //有返回值函數,默認最後一句就是返回值,能夠省略return def helloName2(name: String): String = { "有返回值函數: " + name } //把匿名函數賦值給變量 val add = (x: Int, y: Int) => x + y //柯里化 def add2(x: Int)(y: Int) = x + y //可變參數 def helloName3(name: String*) = { name.foreach(x => print("可變參數: " + x + "\t")) } //默認參數值 def helloPrintName4(name: String = "china") = { println("默認參數值: " + name) } def main(args: Array[String]): Unit = { helloPrintName1("scala") helloPrintName2("scala") println(helloName1("scala")) println(helloName2("scala")) println("把匿名函數賦值給變量", add(1, 2)) println("柯里化", add2(1)(2)) helloName3("zhangsan", "lisi", "wangwu") println() helloPrintName4() helloPrintName4("Korean") } }

測試

  • 案例2
import java.util.Date object Test { //遞歸方法5的階乘 def recursive(num: Int): Int = { if (num == 1) num else num * recursive(num - 1) } //偏應用函數 def log(author: String, date: Date, msg: String) = { println(s"$author:date is " + date + ",log is " + msg) } val date = new Date() val author = "Heaton" //想要調用log,以上變化的是第三個參數,能夠用偏應用函數處理 val logWithDate = log(author, date, _: String) def main(args: Array[String]): Unit = { println("遞歸方法5的階乘", recursive(5)) log(author,date, "log1") log(author,date, "log2") logWithDate("log33") logWithDate("log44") } }

測試

  • 案例3高階函數及柯里化
object Test extends App { //函數的參數是函數 def sum(v1: Int, v2: Int): Int = { v1 + v2 } def hightSum(f: (Int, Int) => Int, a: Int, b: Int): Int = { f(a, b) } println("函數的參數是函數", hightSum(sum, 1, 2)) println("函數的參數是函數->使用匿名函數", hightSum((x: Int, y: Int) => x + y, 2, 2)) //函數的返回是函數(柯里化就是簡寫) //1,2,3,4相加 def hightSum2(a: Int, b: Int): (Int, Int) => Int = { def f2(v1: Int, v2: Int): Int = { v1 + v2 + a + b } f2 } println("函數的返回是函數" + hightSum2(1, 2)(3, 4)) //函數的參數是函數,函數的返回是函數 def hightFun(f: (Int, Int) => Int): (Int, Int) => Int = { f } println("函數的參數是函數" + hightFun(sum)(100, 200)) println("函數的參數是函數->匿名函數" + hightFun((a, b) => a + b)(200, 200)) //若是函數的參數在方法體中只使用了一次 那麼能夠寫成_表示 println("函數的參數是函數->簡寫" + hightFun(_ + _)(200, 200)) //柯里化函數 def currie(a: Int, b: Int)(c: Int, d: Int) = { a + b + c + d } println("柯里化函數" + currie(1, 2)(3, 4)) }

測試

6 集合

6.1 數組

  • 案例
import scala.collection.mutable.ArrayBuffer

object Test extends App {
  /** * 建立定長數組兩種方式: * 1.new Array[String](3) * 2.直接Array */ //建立類型爲Int 長度爲3的數組 val arr1 = new Array[String](3) //建立String 類型的數組,直接賦值 val arr2 = Array[String]("1", "2", "3") //賦值 arr1(0) = "100" arr1(1) = "200" arr1(2) = "300" /** * 遍歷兩種方式 */ print("for循環遍歷" + "\t") for (i <- arr1) { print(i + "\t") } println() print("foreach遍歷" + "\t") arr1.foreach(x => print(x + "\t")) println() print("foreach遍歷" + "\t") arr1.foreach(print) println() /** * 數組的一些經常使用方法 */ //拼接方法 var arr3 = Array.concat(arr1, arr2) print("拼接方法結果:" + "\t") arr3.foreach((x) => print(x + "\t")) println() //初始賦值方法 print("初始賦值結果:" + "\t") var arr4 = Array.fill(3)("hello") arr4.foreach((x) => print(x + "\t")) println() /** * 建立二維數組和遍歷 */ val arr5 = new Array[Array[String]](2) arr5(0) = Array("1", "2", "3") arr5(1) = Array("4", "5", "6") println("二維數組遍歷結果:") for (i <- 0 until arr5.length) { for (j <- 0 until arr5(i).length) { print(arr5(i)(j) + " ") } } println() println("二維數組遍歷結果:") for (i <- 0 until arr5.length; j <- 0 until arr5(i).length) { print(arr5(i)(j) + " ") } println() println("二維數組遍歷結果:") arr5.foreach { arr => { arr.foreach { (x) => print(x + "\t") } } } println() /** * 可變長度數組的定義 */ val arr = ArrayBuffer[String]("a", "b", "c") arr.append("hello", "scala") //在元素末尾追加多個元素 arr.+=("end1", "end2") //在最後追加多個元素 arr.+=:("start") //在開頭添加元素 print("可變數組遍歷" + "\t") arr.foreach((x) => print(x + "\t")) }

測試

  • 經常使用方法
方法 描述
def apply( x: T, xs: T* ): Array[T] 建立指定對象 T 的數組, T 的值能夠是 Unit, Double, Float, Long, Int, Char, Short, Byte, Boolean。
def concatT: Array[T] 合併數組
def copy( src: AnyRef, srcPos: Int, dest: AnyRef, destPos: Int, length: Int ): Unit 複製一個數組到另外一個數組上。相等於 Java's System.arraycopy(src, srcPos, dest, destPos, length)。
def empty[T]: Array[T] 返回長度爲 0 的數組
def iterateT( f: (T) => T ): Array[T] 返回指定長度數組,每一個數組元素爲指定函數的返回值。
def fillT(elem: => T): Array[T] 返回數組,長度爲第一個參數指定,同時每一個元素使用第二個參數進行填充。
def fillT( elem: => T ): Array[Array[T]] 返回二數組,長度爲第一個參數指定,同時每一個元素使用第二個參數進行填充。
def ofDimT: Array[T] 建立指定長度的數組
def ofDimT: Array[Array[T]] 建立二維數組
def ofDimT: Array[Array[Array[T]]] 建立三維數組
def range( start: Int, end: Int, step: Int ): Array[Int] 建立指定區間內的數組,step 爲每一個元素間的步長
def range( start: Int, end: Int ): Array[Int] 建立指定區間內的數組
def tabulateT(f: (Int)=> T): Array[T] 返回指定長度數組,每一個數組元素爲指定函數的返回值,默認從 0 開始。
def tabulateT( f: (Int, Int ) => T): Array[Array[T]] 返回指定長度的二維數組,每一個數組元素爲指定函數的返回值,默認從 0 開始。

6.2 列表List

  • 案例
import scala.collection.mutable.ListBuffer

object Test extends App {
  //建立 val list = List(1, 2, 3, 4, 5) //取出某一個 println("取出某一個", list(0)) //遍歷 print("遍歷\t") list.foreach { x => print(x + "\t") } println() //filter過濾 val list1 = list.filter { x => x > 3 } print("filter過濾結果\t") list1.foreach { x => print(x + "\t") } println() //count統計個數 val value = list.count(x => x > 3) println("count統計結果:" + value) //map val nameList = List("hello hadoop", "hello scala", "hello world") val mapResult: List[Array[String]] = nameList.map(x => x.split(" ")) print("map處理結果\t") mapResult.foreach(x => print(x.toString + "\t")) println() print("map處理結果\t") mapResult.foreach(x => x.foreach(y => print(y + "\t"))) println() //flatmap val flatMapResult: List[String] = nameList.flatMap(x => x.split(" ")) print("flatmap處理結果\t") flatMapResult.foreach(x => print(x.toString + "\t")) println() /** * 可變長list */ val listBuffer: ListBuffer[Int] = ListBuffer[Int](1,2,3,4,5) listBuffer.append(6,7,8,9)//追加元素 listBuffer.+=(10)//在後面追加元素 listBuffer.+=:(100)//在開頭加入元素 print("可變長list遍歷\t") listBuffer.foreach(x => print(x.toString + "\t")) }

測試

  • 經常使用方法
方法 描述
def +(elem: A): List[A] 前置一個元素列表
def ::(x: A): List[A] 在這個列表的開頭添加的元素。
def :::(prefix: List[A]): List[A] 增長了一個給定列表中該列表前面的元素。
def ::(x: A): List[A] 增長了一個元素x在列表的開頭
def addString(b: StringBuilder): StringBuilder 追加列表的一個字符串生成器的全部元素。
def addString(b: StringBuilder, sep: String): StringBuilder 追加列表的使用分隔字符串一個字符串生成器的全部元素。
def apply(n: Int): A 選擇經過其在列表中索引的元素
def contains(elem: Any): Boolean 測試該列表中是否包含一個給定值做爲元素。
def copyToArray(xs: Array[A], start: Int, len: Int): Unit 列表的副本元件陣列。填充給定的數組xs與此列表中最多len個元素,在位置開始。
def distinct: List[A] 創建從列表中沒有任何重複的元素的新列表。
def drop(n: Int): List[A] 返回除了第n個的全部元素。
def dropRight(n: Int): List[A] 返回除了最後的n個的元素
def dropWhile(p: (A) => Boolean): List[A] 丟棄知足謂詞的元素最長前綴。
def endsWithB: Boolean 測試列表是否使用給定序列結束。
def equals(that: Any): Boolean equals方法的任意序列。比較該序列到某些其餘對象。
def exists(p: (A) => Boolean): Boolean 測試謂詞是否持有一些列表的元素。
def filter(p: (A) => Boolean): List[A] 返回列表知足謂詞的全部元素。
def forall(p: (A) => Boolean): Boolean 測試謂詞是否持有該列表中的全部元素。
def foreach(f: (A) => Unit): Unit 應用一個函數f以列表的全部元素。
def head: A 選擇列表的第一個元素
def indexOf(elem: A, from: Int): Int 通過或在某些起始索引查找列表中的一些值第一次出現的索引。
def init: List[A] 返回除了最後的全部元素
def intersect(that: Seq[A]): List[A] 計算列表和另外一序列之間的多重集交集。
def isEmpty: Boolean 測試列表是否爲空
def iterator: Iterator[A] 建立一個新的迭代器中包含的可迭代對象中的全部元素
def last: A 返回最後一個元素
def lastIndexOf(elem: A, end: Int): Int 以前或在一個給定的最終指數查找的列表中的一些值最後一次出現的索引
def length: Int 返回列表的長度
def mapB: List[B] 經過應用函數以g這個列表中的全部元素構建一個新的集合
def max: A 查找最大的元素
def min: A 查找最小元素
def mkString: String 顯示列表的字符串中的全部元素
def mkString(sep: String): String 顯示的列表中的字符串中使用分隔串的全部元素
def reverse: List[A] 返回新列表,在相反的順序元素
def sorted[B >: A]: List[A] 根據排序對列表進行排序
def startsWithB: Boolean 測試該列表中是否包含給定的索引處的給定的序列
def sum: A 歸納這個集合的元素
def tail: List[A] 返回除了第一的全部元素
def take(n: Int): List[A] 返回前n個元素
def takeRight(n: Int): List[A] 返回最後n個元素
def toArray: Array[A] 列表以一個數組變換
def toBuffer[B >: A]: Buffer[B] 列表以一個可變緩衝器轉換
def toMap[T, U]: Map[T, U] 此列表的映射轉換
def toSeq: Seq[A] 列表的序列轉換
def toSet[B >: A]: Set[B] 列表到集合變換
def toString(): String 列表轉換爲字符串

6.3 集合set

  • 案例1
object Test extends App { //建立 val set1 = Set(1, 2, 3, 4, 4) val set2 = Set(1, 2, 5) //遍歷 set會自動去重 print("遍歷\t") set1.foreach(x => print(x + "\t")) println() print("遍歷\t") for (s <- set1) { print(s + "\t") } println() //交集 val set3 = set1.intersect(set2) print("交集遍歷\t") set3.foreach(x => print(x + "\t")) println() val set4 = set1.&(set2) print("交集遍歷\t") set4.foreach(x => print(x + "\t")) println() //差集 print("差集遍歷\t") set1.diff(set2).foreach(x => print(x + "\t")) println() print("差集遍歷\t") set1.&~(set2).foreach(x => print(x + "\t")) println() //子集 println("是不是子集\t"+set1.subsetOf(set2)) //最大值 println("最大值\t"+set1.max) //最小值 println("最小值\t"+set1.min) //轉成數組,list print("轉成數組\t") set1.toArray.foreach(x => print(x + "\t")) println() print("轉成列表\t") set1.toList.foreach(x => print(x + "\t")) println() //mkString集合全部元素做爲字符串顯示 println("集合全部元素做爲字符串顯示"+set1.mkString) println("集合全部元素做爲字符串顯示分隔符\t"+set1.mkString("\t")) }

測試

  • 案例2
import scala.collection.mutable
import scala.collection.immutable
object Test extends App {
  /**
 * 可變長Set->scala.collection.mutable.Set  * 不可變長Set->scala.collection.immutable.Set  */ val set1 = mutable.Set[Int](1,2,3,4,5) val set2 = immutable.Set[Int](1,2,3,4,5) set1.add(100) set1.+=(200) set1.+=(1,210,300) print("可變長set遍歷") set1.foreach(x=>print(x+"\t")) //set2.add(100) 報錯 }

測試

  • 經常使用方法
方法 描述
def +(elem: A): Set[A] 爲集合添加新元素,x並建立一個新的集合,除非元素已存在
def -(elem: A): Set[A] 移除集合中的元素,並建立一個新的集合
def contains(elem: A): Boolean 若是元素在集合中存在,返回 true,不然返回 false。
def &(that: Set[A]): Set[A] 返回兩個集合的交集
def &~(that: Set[A]): Set[A] 返回兩個集合的差集
def +(elem1: A, elem2: A, elems: A*): Set[A] 經過添加傳入指定集合的元素建立一個新的不可變集合
def ++(elems: A): Set[A] 合併兩個集合
def -(elem1: A, elem2: A, elems: A*): Set[A] 經過移除傳入指定集合的元素建立一個新的不可變集合
def addString(b: StringBuilder): StringBuilder 將不可變集合的全部元素添加到字符串緩衝區
def addString(b: StringBuilder, sep: String): StringBuilder 將不可變集合的全部元素添加到字符串緩衝區,並使用指定的分隔符
def apply(elem: A) 檢測集合中是否包含指定元素
def count(p: (A) => Boolean): Int 計算知足指定條件的集合元素個數
def copyToArray(xs: Array[A], start: Int, len: Int): Unit 複製不可變集合元素到數組
def diff(that: Set[A]): Set[A] 比較兩個集合的差集
def drop(n: Int): Set[A]] 返回丟棄前n個元素新集合
def dropRight(n: Int): Set[A] 返回丟棄最後n個元素新集合
def dropWhile(p: (A) => Boolean): Set[A] 從左向右丟棄元素,直到條件p不成立
def equals(that: Any): Boolean equals 方法可用於任意序列。用於比較系列是否相等。
def exists(p: (A) => Boolean): Boolean 判斷不可變集合中指定條件的元素是否存在。
def filter(p: (A) => Boolean): Set[A] 輸出符合指定條件的全部不可變集合元素。
def find(p: (A) => Boolean): Option[A] 查找不可變集合中知足指定條件的第一個元素
def forall(p: (A) => Boolean): Boolean 查找不可變集合中知足指定條件的全部元素
def foreach(f: (A) => Unit): Unit 將函數應用到不可變集合的全部元素
def head: A 獲取不可變集合的第一個元素
def init: Set[A] 返回全部元素,除了最後一個
def intersect(that: Set[A]): Set[A] 計算兩個集合的交集
def isEmpty: Boolean 判斷集合是否爲空
def iterator: Iterator[A] 建立一個新的迭代器來迭代元素
def last: A 返回最後一個元素
def mapB: immutable.Set[B] 經過給定的方法將全部元素從新計算
def max: A 查找最大元素
def min: A 查找最小元素
def mkString: String 集合全部元素做爲字符串顯示
def mkString(sep: String): String 使用分隔符將集合全部元素做爲字符串顯示
def product: A 返回不可變集合中數字元素的積。
def size: Int 返回不可變集合元素的數量
def splitAt(n: Int): (Set[A], Set[A]) 把不可變集合拆分爲兩個容器,第一個由前 n 個元素組成,第二個由剩下的元素組成
def subsetOf(that: Set[A]): Boolean 若是集合A中含有子集B返回 true,不然返回false
def sum: A 返回不可變集合中全部數字元素之和
def tail: Set[A] 返回一個不可變集合中除了第一元素以外的其餘元素
def take(n: Int): Set[A] 返回前 n 個元素
def takeRight(n: Int):Set[A] 返回後 n 個元素
def toArray: Array[A] 將集合轉換爲數組
def toBuffer[B >: A]: Buffer[B] 返回緩衝區,包含了不可變集合的全部元素
def toList: List[A] 返回 List,包含了不可變集合的全部元素
def toMap[T, U]: Map[T, U] 返回 Map,包含了不可變集合的全部元素
def toSeq: Seq[A] 返回 Seq,包含了不可變集合的全部元素
def toString(): String 返回一個字符串,以對象來表示

6.4 map

  • 案例1
object Test extends App { val map = Map[String, Int]("a" -> 100, "b" -> 200, ("c", 300), ("c", 400)) val option1: Option[Int] = map.get("a") val option2: Option[Int] = map.get("aa") println("從map中取鍵爲a的值\t"+option1) println("從map中取鍵爲a的值\t"+option1.get) println("從map中取鍵爲aa的值\t"+option2) println("從map中取鍵爲aa的值\t"+option2.getOrElse("no value")) print("遍歷:") println(map) print("遍歷:") for (elem <- map) { print(elem + "\t") } println() print("遍歷鍵->拿到值:") val keys: Iterable[String] = map.keys keys.foreach(key => { val value = map.get(key).get print(s"key = $key ,value = $value\t") }) println() print("遍歷值:") val values: Iterable[Int] = map.values values.foreach(x => print(x + "\t")) println() val map1 = Map[String, Int](("a", 1), ("b", 2), ("c", 3), ("d", 4)) val map2 = Map[String, Int](("a", 100), ("b", 2), ("c", 300), ("e", 500)) val result1: Map[String, Int] = map1.++(map2) val result2: Map[String, Int] = map1.++:(map2) print("合併後的結果:") result1.foreach(x => print(x + "\t")) println() print("合併後的結果:") result2.foreach(x => print(x + "\t")) println() }

測試

  • 案例2
import scala.collection.mutable import scala.collection.immutable object Test extends App { //不可變長map->scala.collection.immutable.Map //可變長map->scala.collection.mutable.Map val map1 = immutable.Map[String, Int]("a" -> 100, "b" -> 200, ("c", 300), ("c", 400)) val map2 = mutable.Map[String, Int]() //map1.put("hello",100)報錯 map2.put("hello", 100) map2.put("world", 200) map2.put("hadoop", 200) print("可變長map遍歷:\t") map2.foreach(x => print(x + "\t")) println() //count val countResult = map2.count(p => { p._1.equals("hadoop") && p._2 == 200 }) println(s"鍵爲hadoop值爲200的元素有 $countResult 個") //filter map2.filter(_._1.equals("world")).foreach(x => println("過濾後的元素", x._1, x._2)) //contains println("是否有鍵爲hello的元素", map2.contains("hello")) //exist println("符合條件的元素存在麼",map2.exists(x => { x._1.equals("hadoop") })) }

測試

  • 經常使用方法
方法 描述
def ++(xs: Map[(A, B)]): Map[A, B] 返回一個新的 Map,新的 Map xs 組成
def -(elem1: A, elem2: A, elems: A*): Map[A, B] 返回一個新的 Map, 移除 key 爲 elem1, elem2 或其餘 elems。
def --(xs: GTO[A]): Map[A, B] 返回一個新的 Map, 移除 xs 對象中對應的 key
def get(key: A): Option[B] 返回指定 key 的值
def iterator: Iterator[(A, B)] 建立新的迭代器,並輸出 key/value 對
def addString(b: StringBuilder): StringBuilder 將 Map 中的全部元素附加到StringBuilder,可加入分隔符
def addString(b: StringBuilder, sep: String): StringBuilder 將 Map 中的全部元素附加到StringBuilder,可加入分隔符
def apply(key: A): B 返回指定鍵的值,若是不存在返回 Map 的默認方法
def clone(): Map[A, B] 從一個 Map 複製到另外一個 Map
def contains(key: A): Boolean 若是 Map 中存在指定 key,返回 true,不然返回 false。
def copyToArray(xs: Array[(A, B)]): Unit 複製集合到數組
def count(p: ((A, B)) => Boolean): Int 計算知足指定條件的集合元素數量
def default(key: A): B 定義 Map 的默認值,在 key 不存在時返回。
def drop(n: Int): Map[A, B] 返回丟棄前n個元素新集合
def dropRight(n: Int): Map[A, B] 返回丟棄最後n個元素新集合
def dropWhile(p: ((A, B)) => Boolean): Map[A, B] 從左向右丟棄元素,直到條件p不成立
def empty: Map[A, B] 返回相同類型的空 Map
def equals(that: Any): Boolean 若是兩個 Map 相等(key/value 均相等),返回true,不然返回false
def exists(p: ((A, B)) => Boolean): Boolean 判斷集合中指定條件的元素是否存在
def filter(p: ((A, B))=> Boolean): Map[A, B] 返回知足指定條件的全部集合
def filterKeys(p: (A) => Boolean): Map[A, B] 返回符合指定條件的的不可變 Map
def find(p: ((A, B)) => Boolean): Option[(A, B)] 查找集合中知足指定條件的第一個元素
def foreach(f: ((A, B)) => Unit): Unit 將函數應用到集合的全部元素
def init: Map[A, B] 返回全部元素,除了最後一個
def isEmpty: Boolean 檢測 Map 是否爲空
def keys: Iterable[A] 返回全部的key/p>
def last: (A, B) 返回最後一個元素
def max: (A, B) 查找最大元素
def min: (A, B) 查找最小元素
def mkString: String 集合全部元素做爲字符串顯示
def product: (A, B) 返回集合中數字元素的積。
def remove(key: A): Option[B] 移除指定 key
def retain(p: (A, B) => Boolean): Map.this.type 若是符合知足條件的返回 true
def size: Int 返回 Map 元素的個數
def sum: (A, B) 返回集合中全部數字元素之和
def tail: Map[A, B] 返回一個集合中除了第一元素以外的其餘元素
def take(n: Int): Map[A, B] 返回前 n 個元素
def takeRight(n: Int): Map[A, B] 返回後 n 個元素
def takeWhile(p: ((A, B)) => Boolean): Map[A, B] 返回知足指定條件的元素
def toArray: Array[(A, B)] 集合轉數組
def toBuffer[B >: A]: Buffer[B] 返回緩衝區,包含了 Map 的全部元素
def toList: List[A] 返回 List,包含了 Map 的全部元素
def toSeq: Seq[A] 返回 Seq,包含了 Map 的全部元素
def toSet: Set[A] 返回 Set,包含了 Map 的全部元素
def toString(): String 返回字符串對象

6.5 元組Tuple

  • val tuple = new Tuple(1) 可使用new
  • val tuple2 = Tuple(1,2) 能夠不使用new,也能夠直接寫成val tuple3 =(1,2,3)
  • 取值用」._XX」 能夠獲取元組中的值
  • 注意:tuple最多支持22個參數
  • 案例
object Test extends App { val tuple1: Tuple1[String] = new Tuple1("hello") val tuple2: (String, Int) = new Tuple2("a", 100) val tuple3: (Int, Boolean, Char) = new Tuple3(1, true, 'C') val tuple4: (Int, Double, String, Boolean) = Tuple4(1, 3.4, "abc", false) val tuple6: (Int, Int, Int, Int, Int, String) = (1, 2, 3, 4, 5, "abc") val tuple22 = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, "abc", 14, 15, 16, 17, 18, 19, 20, 21, 22) println("針對2元組的倒轉方法" + tuple2.swap) val value: String = tuple22._13 println("取值", value) println("輸出整個元組" + tuple4) print("遍歷:\t") val iter: Iterator[Any] = tuple6.productIterator while (iter.hasNext) { print(iter.next() + "\t") } println() print("遍歷:\t") tuple6.productIterator.foreach(x => print(x + "\t")) }

測試

7 抽象類

  • 案例
abstract class Person { def speak val name: String var age: Int } class Student extends Person { val name = "zhangsan" var age = 10 def speak = { println("speak!!!") } } object code extends App { val s = new Student s.speak println(s.name + ":" + s.age) }

測試

8 Trait特性(可以帶有具體實現的接口)

  • 案例1
/** * 一個類繼承多個trait時,第一個關鍵字使用 extends,以後使用with * trait 不能夠傳參 */ trait Read { def read(name: String) = { println(s"$name is reading...") } } trait Listen { def listen(name: String) = { println(s"$name is listening...") } } class Human() extends Read with Listen { } object Test extends App { val h = new Human() h.read("zhangsan") h.listen("lisi") }

測試

  • 案例2
/** * Trait中能夠有方法體的實現或者方法體的不實現,類繼承了Trait要實現Trait中沒有實現的方法 */ trait IsEquale{ def isEqu(o:Any):Boolean def isNotEqu(o:Any) :Boolean = !isEqu(o) } class Point(xx:Int,xy:Int) extends IsEquale { val x = xx val y = xy override def isEqu(o: Any): Boolean = { o.isInstanceOf[Point]&&o.asInstanceOf[Point].x==this.x } } object Test extends App { val p1 = new Point(1,2) val p2 = new Point(1,3) println(p1.isNotEqu(p2)) }

測試

7 apply()方法 及 靜態方法 及 單例

  • 案例1
class ApplyTest{ def apply() = "Apply" def test{ println("test") } } object ApplyTest{ def apply() = new ApplyTest() } object Test extends App { val a = ApplyTest()//類加()調用了對象的apply()方法 a.test val t = new ApplyTest print(t())//對象加()就是調用類的apply()方法 }

測試

  • 案例2
object ApplyTest { var count = 0 def incr: Unit = { count = count + 1 } } object Test extends App { for (i <- 1 until 10) { ApplyTest.incr } print(ApplyTest.count) }

測試

8 隱式轉換

  • 隱式轉換是在Scala編譯器進行類型匹配時,若是找不到合適的類型,那麼隱式轉換會讓編譯器在做用範圍內自動推導出來合適的類型。
  • 1.隱式值與隱式參數
    • 隱式值是指在定義參數時前面加上implicit。隱式參數是指在定義方法時,方法中的部分參數是由implicit修飾【必須使用柯里化的方式,將隱式參數寫在後面的括號中】。隱式轉換做用就是:當調用方法時,沒必要手動傳入方法中的隱式參數,Scala會自動在做用域範圍內尋找隱式值自動傳入。
    • 隱式值和隱式參數注意:
      • 1). 同類型的參數的隱式值只能在做用域內出現一次,同一個做用域內不能定義多個類型同樣的隱式值。
      • 2). implicit 關鍵字必須放在隱式參數定義的開頭
      • 3). 一個方法只有一個參數是隱式轉換參數時,那麼能夠直接定義implicit關鍵字修飾的參數,調用時直接建立類型不傳入參數便可。
      • 4). 一個方法若是有多個參數,要實現部分參數的隱式轉換,必須使用柯里化這種方式,隱式關鍵字出如今後面,只能出現一次
  • 2.隱式轉換函數
    • 隱式轉換函數是使用關鍵字implicit修飾的方法。當Scala運行時,假設若是A類型變量調用了method()這個方法,發現A類型的變量沒有method()方法,而B類型有此method()方法,會在做用域中尋找有沒有隱式轉換函數將A類型轉換成B類型,若是有隱式轉換函數,那麼A類型就能夠調用method()這個方法。
    • 隱式轉換函數注意:隱式轉換函數只與函數的參數類型和返回類型有關,與函數名稱無關,因此做用域內不能有相同的參數類型和返回類型的不一樣名稱隱式轉換函數。
  • 3.隱式類
    • 使用implicit關鍵字修飾的類就是隱式類。若一個變量A沒有某些方法或者某些變量時,而這個變量A能夠調用某些方法或者某些變量時,能夠定義一個隱式類,隱式類中定義這些方法或者變量,隱式類中傳入A便可。
    • 隱式類注意:
      • 1).隱式類必須定義在類,包對象,伴生對象中。
      • 2).隱式類的構造必須只有一個參數,同一個類,包對象,伴生對象中不能出現同類型構造的隱式類。
  • 案例1
object Test extends App { def Student(age: Int)(implicit name: String, i: Int) = { println(s"student :$name ,age = $age ,score = $i") } def Teacher(implicit name: String) = { println(s"teacher name is = $name") } implicit val zs: String = "zhangsan" implicit val sr: Int = 100 Student(18) Teacher }

測試

  • 案例2
class Animal(name: String) { def canFly(): Unit = { println(s"$name can fly...") } } class Rabbit(xname: String) { val name = xname } object Test extends App { implicit def rabbitToAnimal(rabbit: Rabbit): Animal = { new Animal(rabbit.name) } val rabbit = new Rabbit("RABBIT") rabbit.canFly() }

測試

  • 案例3
class Rabbit(s: String) { val name = s } object Test extends App { implicit class Animal(rabbit: Rabbit) { val tp = "Animal" def canFly() = { println(rabbit.name + " can fly...") } } val rabbit = new Rabbit("rabbit") rabbit.canFly() println(rabbit.tp) }

測試

9 Actor 通信模型

  • Actor Model是用來編寫並行計算或分佈式系統的高層次抽象(相似java中的Thread)讓程序員沒必要爲多線程模式下共享鎖而煩惱,被用在Erlang 語言上, 高可用性99.9999999 % 一年只有31ms 宕機Actors將狀態和行爲封裝在一個輕量的進程/線程中,可是不和其餘Actors分享狀態,每一個Actors有本身的世界觀,當須要和其餘Actors交互時,經過發送事件和消息,發送是異步的,非堵塞的(fire-andforget),發送消息後沒必要等另外Actors回覆,也沒必要暫停,每一個Actors有本身的消息隊列,進來的消息按先來後到排列,這就有很好的併發策略和可伸縮性,能夠創建性能很好的事件驅動系統。
  • Actor的特徵:
    • ActorModel是消息傳遞模型,基本特徵就是消息傳遞
    • 消息發送是異步的,非阻塞的
    • 消息一旦發送成功,不能修改
    • Actor之間傳遞時,本身決定決定去檢查消息,而不是一直等待,是異步非阻塞的
  • 什麼是Akka
    • Akka 是一個用 Scala 編寫的庫,用於簡化編寫容錯的、高可伸縮性的 Java 和Scala 的 Actor 模型應用,底層實現就是Actor,Akka是一個開發庫和運行環境,能夠用於構建高併發、分佈式、可容錯、事件驅動的基於JVM的應用。使構建高併發的分佈式應用更加容易。
    • spark1.6版本以前,spark分佈式節點之間的消息傳遞使用的就是Akka,底層也就是actor實現的。1.6以後使用的netty傳輸。
  • 案例1
import scala.actors.Actor class myActor extends Actor { def act() { while (true) { receive { case x: String => println("get String =" + x) case x: Int => println("get Int") case _ => println("get default") } } } } object Test extends App { //建立actor的消息接收和傳遞 val actor = new myActor() //啓動 actor.start() //發送消息寫法 actor ! "i love you !" actor ! 500 actor ! true }

測試

  • 案例2 Actor與Actor之間通訊
import scala.actors.Actor case class Message(actor: Actor, msg: Any) class Actor1 extends Actor { def act() { while (true) { receive { case msg: Message => { println("i sava msg! = " + msg.msg) msg.actor ! "i love you too !" } case msg: String => println(msg) case _ => println("default msg!") } } } } class Actor2(actor: Actor) extends Actor { actor ! Message(this, "i love you !") def act() { while (true) { receive { case msg: String => { if (msg.equals("i love you too !")) { println(msg) actor ! "could we have a date !" } } case _ => println("default msg!") } } } } object Test extends App { val actor1 = new Actor1() actor1.start() val actor2 = new Actor2(actor1) actor2.start() }

測試

相關文章
相關標籤/搜索