1. 程式人生 > >1.1 scala學習筆記

1.1 scala學習筆記

1.1.什麼是Scala
Scala是一種多正規化(面向物件(包含了面向過程的),面向函式)的程式語言,其設計的初衷是要整合面向物件程式設計和函數語言程式設計的各種特性。Scala運行於Java平臺(Java虛擬機器),併兼容現有的Java程式。
1.7以上
Java 1.8
1.2.為什麼要學Scala
1.優雅:這是框架設計師第一個要考慮的問題,框架的使用者是應用開發程式設計師,API是否優雅直接影響使用者體驗。
2.速度快:Scala語言表達能力強,一行程式碼抵得上Java多行,開發速度快;Scala是靜態編譯的,所以和JRuby,Groovy比起來速度會快很多。
Java scala 架構大型的專案 資料處理能力也很好
3. 能融合到Hadoop生態圈:Hadoop現在是大資料事實標準,Spark並不是要取代Hadoop,而是要完善Hadoop生態。JVM語言大部分可能會想到Java,但Java做出來的API太醜,或者想實現一個優雅的API太費勁。 (python)
Scala Spark
Python(爬蟲,網站開發,資料分析,機器學習,深度學習,spark,運維)
Java/php/.net/ 移動開發(安卓,IOS)
大資料
安卓
Spring Hibernate Struct hadoop hbase storm mybatis
非常成熟產品。
2.Scala編譯器安裝
2.1.安裝JDK
因為Scala是執行在JVM平臺上的,所以安裝Scala之前要安裝JDK
2.2.安裝Scala
2.2.1.Windows安裝Scala編譯器
訪問Scala官網

http://www.scala-lang.org/下載Scala編譯器安裝包,目前最新版本是2.12.x,但是目前大多數的框架都是用2.11.x編寫開發的,Spark2.x使用的就是2.11.x,所以這裡推薦2.11.x版本,下載scala-2.11.8.msi後點擊下一步就可以了
2.2.2.Linux安裝Scala編譯器
下載Scala地址http://downloads.typesafe.com/scala/2.11.8/scala-2.11.8.tgz然後解壓Scala到指定目錄
tar -zxvf scala-2.11.8.tgz -C /usr/java
配置環境變數,將scala加入到PATH中
vi /etc/profile
export JAVA_HOME=/usr/java/jdk1.8.0_111
export PATH=P
ATH:
JAVA_HOME/bin:/usr/java/scala-2.11.8/bin
2.2.3.Scala開發工具安裝
目前Scala的開發工具主要有兩種:Eclipse和IDEA,這兩個開發工具都有相應的Scala外掛,如果使用Eclipse,直接到Scala官網下載即可http://scala-ide.org/download/sdk.html
由於IDEA的Scala外掛更優秀,大多數Scala程式設計師都選擇IDEA,可以到http://www.jetbrains.com/idea/download/下載社群免費版,點選下一步安裝即可,安裝時如果有網路可以選擇線上安裝Scala外掛。這裡我們使用離線安裝Scala外掛:
1.安裝IDEA,點選下一步即可。由於我們離線安裝外掛,所以點選Skip All and Set Defaul
2.下載IEDA的scala外掛,地址
http://plugins.jetbrains.com/?idea_ce

這裡寫圖片描述
3.安裝Scala外掛:Configure -> Plugins -> Install plugin from disk -> 選擇Scala外掛 -> OK -> 重啟IDEA
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述
3.Scala基礎
3.1.宣告變數

object VariableTest {
  def main(args: Array[String]) {
    //使用val定義的變數值是不可變的,相當於java裡用final修飾的變數
    val i = 1
    //使用var定義的變數是可變得,在Scala中鼓勵使用val
    var s = "hello"
    //Scala編譯器會自動推斷變數的型別,必要的時候可以指定型別
    //變數名在前,型別在後
    val str: String = "world"
  }
}

3.2.常用型別
Scala和Java一樣,有7種數值型別Byte、Char、Short、Int、Long、Float和Double和一個Boolean型別
3.3.條件表示式
Scala的的條件表示式比較簡潔,例如:

object ConditionTest {
  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)
  }
}

這裡寫圖片描述
這裡寫圖片描述
條件表示式有返回值,需要有一個變數去接收,系統會自動生成
這裡寫圖片描述
3.4.塊表示式

object BlockExpressionTest {
  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)
  }
}

這裡寫圖片描述
3.5.迴圈
在scala中有for迴圈和while迴圈,用for迴圈比較多
for迴圈語法結構:for (i <- 表示式/陣列/集合)

object ForTest {
  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迴圈
    //每個生成器都可以帶一個條件,注意:if前面沒有分號
    for(i <- 1 to 3; j <- 1 to 3 if i != j)
      print((10 * i + j) + " ")
    println()

    //for推導式:如果for迴圈的迴圈體以yield開始,則該迴圈會構建出一個集合
    //每次迭代生成集合中的一個值
    val v = for (i <- 1 to 10) yield i * 10
    println(v)
  }
}

這裡寫圖片描述
所有的偶數 * 2
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述
3.6.呼叫方法和函式
Scala中的+ - * / %等操作符的作用與Java一樣,位操作符 & | ^ >> <<也一樣。只是有
一點特別的:這些操作符實際上是方法。例如:
a + b
是如下方法呼叫的簡寫:
a.+(b)
a 方法 b可以寫成 a.方法(b)
3.7.定義方法和函式
3.7.1.定義方法
這裡寫圖片描述
方法的返回值型別可以不寫,編譯器可以自動推斷出來,但是對於遞迴函式,必須指定返回型別
這裡寫圖片描述
方法的返回值不寫,編譯器可以自動推斷出來,為Unit(相當於java中的void)
3.7.2.定義函式
這裡寫圖片描述
function2:表示函式的引數為2個
函式的修飾符 val ,方法的修飾符是def,
函式名後面有 =,方法名後面沒有=,直接是方法體
函式體後面是 =>,沒有返回值型別,方法可以通過 :Int= 來指定放回型別
函式和方法的呼叫方式一樣
這裡寫圖片描述
3.7.3.方法和函式的區別
在函數語言程式設計語言中,函式是“頭等公民”,它可以像任何其他資料型別一樣被傳遞和操作
案例:首先定義一個方法,再定義一個函式,然後將函式傳遞到方法裡面
這裡寫圖片描述

object MethodAndFunctionTest {
  //定義一個方法
  //方法m2引數要求是一個函式,函式的引數必須是兩個Int型別
  //返回值型別也是Int型別
  def m1(f: (Int, Int) => Int) : Int = {
    f(2, 6)
  }

  //定義一個函式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中傳遞的函式形式與建立完函式的形式一直,f(2,6)表示方法傳入的兩個引數,然後方法在傳入方法,可以實現靈活的呼叫函式。
這裡寫圖片描述
array.map()中傳入方法f3與直接傳入方法體的效果一樣
這裡寫圖片描述
一步一步簡化方法體
map()方法中應該可以遍歷陣列array
這裡寫圖片描述
3.7.4.將方法轉換成函式(神奇的下劃線)
這裡寫圖片描述