1. 程式人生 > >scala的簡介安裝與基礎語法

scala的簡介安裝與基礎語法

class 目錄 高階函數 參數 repl str sed 加強 閉包

大數據技術之Scala

==========第一篇:Scala編程語言=========

一、Scala語言基礎

1Scala簡介

Scala是一種多範式的編程語言,其設計的初衷是要集成面向對象編程和函數式編程的各種特性。Scala運行於Java平臺(Java虛擬機),並兼容現有的Java程序。它也能運行於CLDC配置的Java ME中。目前還有另一.NET平臺的實現,不過該版本更新有些滯後。Scala的編譯模型(獨立編譯,動態類加載)與JavaC#一樣,所以Scala代碼可以調用Java類庫(對於.NET實現則可調用.NET類庫)。Scala包括編譯器和類庫,以及BSD許可證發布。

學習Scala編程語言,為後續學習Spark奠定基礎。

2Scala安裝與配置

安裝

Scala需要Java運行時庫,安裝Scala需要首先安裝JVM虛擬機,推薦安裝JDK1.8

http://www.scala-lang.org/ 下載Scala2.11.8程序安裝包

根據不同的操作系統選擇不同的安裝包,下載完成後,將安裝包解壓到安裝目錄。

註意:安裝時,安裝路徑中不能含有空格。

scala安裝目錄下的bin目錄加入到PATH環境變量:

SCALA_HOME:

SCALA_HOME= D:\scala-2.11.8

PATH:

PATH變量中添加:%SCALA_HOME%\bin

完成以上流程後,在命令行輸入:scala,進入如下界面:

註意:該操作WindowsLinux配置流程是一樣的。可以參考JavaJDK的配置過程。

到此為止,Scala的安裝已經成功。

配置IDEA

1) 打開IDEA工具,如圖:點擊Configure

2) 點擊Plugins

3) 點擊Install plugin from disk

4) 選擇scalaplugins

5) 此時會顯示一個Scala的條目,在右側點擊Restart IntelliJ

IDEA

6) 創建Maven項目

創建的maven項目默認是不支持scala的,需要為項目添加scalaframework,如圖:

在這裏選擇Scala後,在右邊的Use library中配置你的安裝目錄即可,最後點擊OK

7) 在項目的目錄結構中,創建scala文件夾,並標記為sourcefile-project structure

8) 以上配置都完成後,就可以在scala上點擊右鍵創建scala class

3Scala的運行環境

l REPLRead Evaluate Print Loop):命令行

l IDE:圖形開發工具

n The Scala IDE (Based on Eclipse)http://scala-ide.org/

n IntelliJ IDEA with Scala pluginhttp://www.jetbrains.com/idea/download/

n Netbeans IDE with the Scala plugin

4Scala的常用數據類型

註意:在Scala中,任何數據都是對象。例如:

① 數值類型:ByteShortIntLongFloatDouble

l Byte: 8位有符號數字,從-128 127

l Short: 16位有符號數據,從-32768 32767

l Int32位有符號數據

l Long64位有符號數據

例如:

val a:Byte = 10

a+10

得到:res9: Int = 20

這裏的res9是新生成變量的名字

val b:Short = 20

a+b

註意:在Scala中,定義變量可以不指定類型,因為Scala會進行類型的自動推導。

② 字符類型和字符串類型:CharString

對於字符串,在Scala中可以進行插值操作。

註意:前面有個s;相當於執行:"My Name is " + s1

③ Unit類型:相當於Java中的void類型

④ Nothing類型:一般表示在執行過程中,產生了Exception

例如,我們定義一個函數如下:

5Scala變量的申明和使用

l 使用valvar申明變量

例如:scala> val answer = 8 * 3 + 2

可以在後續表達式中使用這些名稱

l val:定義的值實際是一個常量

要申明其值可變的變量:var

註意:可以不用顯式指定變量的類型,Scala會進行自動的類型推到

6Scala的函數和方法的使用

l 可以使用Scala的預定義函數

例如:求兩個值的最大值

l 也可以使用def關鍵字自定義函數

語法:

示例:

7Scala的條件表達式

Scalaif/else語法結構和JavaC++一樣。

不過,在Scala中,if/else是表達式,有值,這個值就是跟在ifelse之後的表達式的值。

8Scala的循環

Scala擁有與JavaC++相同的whiledo循環

Scala中,可以使用forforeach進行叠代

  • 使用for循環案例:

註意:

*<- 表示Scala中的generator,即:提取符

*)第三種寫法是第二種寫法的簡寫

  • for循環中,還可以使用yield關鍵字來產生一個新的集合

在上面的案例中,我們將list集合中的每個元素轉換成了大寫,並且使用yield關鍵字生成了一個新的集合。

  • 使用while循環:註意使用小括號,不是中括號

  • 使用do ... while循環

  • 使用foreach進行叠代

註意:在上面的例子中,foreach接收了另一個函數(println)作為值

9Scala函數的參數

  • Scala中,有兩種函數參數的求值策略

l Call By Value:對函數實參求值,且僅求一次

l Call By Name:函數實參每次在函數體內被用到時都會求值

我們來分析一下,上面兩個調用執行的過程:

一份復雜一點的例子:

  • Scala中的函數參數

l 默認參數

l 代名參數

l 可變參數

10ScalaLazy值(懶值)

val被申明為lazy時,它的初始化將被推遲,直到我們首次對它取值。

一個更為復雜一點的例子:讀取文件:

11、異常的處理

Scala異常的工作機制和Java或者C++一樣。直接使用throw關鍵字拋出異常。

12Scala中的數組

Scala數組的類型:

l 定長數組:使用關鍵字Array

l 變長數組:使用關鍵字ArrayBuffer

l 遍歷數組

l Scala數組的常用操作

l Scala的多維數組

l Java一樣,多維數組是通過數組的數組來實現的。

l 也可以創建不規則的數組,每一行的長度各不相同。

13、映射

映射就是Map集合,由一個(key,value)組成。

-> 操作符用來創建

例如:

val scores = Map(Alice-> 10,Bob-> 3,Cindy-> 8)

映射的類型分為:不可變Map和可變Map

映射的操作

l 獲取映射中的值

l 更新映射中的值(必須是可變Map

l 叠代映射

14、元組(Tuple

元組是不同類型的值的聚集。

例如:val t = (1, 3.14, "Fred") // 類型為Tuple3[Int, Double, java.lang.String]

這裏:Tuple是類型,3是表示元組中有三個元素。

元組的訪問和遍歷:

註意:要遍歷Tuple中的元素,需要首先生成對應的叠代器。不能直接使用for或者foreach

二、Scala語言的面向對象

1、面向對象的基本概念

把數據及對數據的操作方法放在一起,作為一個相互依存的整體——對象

面向對象的三大特征:

u 封裝

u 繼承

u 多態

2、類的定義

簡單類和無參方法:

案例:註意沒有class前面沒有public關鍵字修飾。

如果要開發main方法,需要將main方法定義在該類的伴生對象中,即:object對象中,(後續做詳細的討論)。

3、屬性的gettersetter方法

l 當定義屬性是private時候,scala會自動為其生成對應的getset方法

private var stuName:String = "Tom"

  • get方法: stuName ----> s2.stuName() 由於stuName是方法的名字,所以可以加上一個括號
  • set方法: stuName_= ----> stuName_= 是方法的名字

l 定義屬性:private var money:Int = 1000 希望money只有get方法,沒有set方法??

  • 辦法:將其定義為常量private val money:Int = 1000

l private[this]的用法:該屬性只屬於該對象私有,就不會生成對應的setget方法。如果這樣,就不能直接調用,例如:s1.stuName ---> 錯誤

4、內部類(嵌套類)

我們可以在一個類的內部在定義一個類,如下:我們在Student類中,再定義了一個Course類用於保存學生選修的課程。

開發一個測試程序進行測試:

5、類的構造器

類的構造器分為:主構造器、輔助構造器

l 主構造器:和類的聲明結合在一起,只能有一個主構造器

Student4(val stuName:String,val stuAge:Int)

(1) 定義類的主構造器:兩個參數

(2) 聲明了兩個屬性:stuNamestuAge 和對應的getset方法

l 輔助構造器:可以有多個輔助構造器,通過關鍵字this來實現

6Scala中的Object對象

Scala沒有靜態的修飾符,但Object對象下的成員都是靜態的 ,若有同名的class,這其作為它的伴生類。在Object中一般可以為伴生類做一些初始化等操作。

下面是Java中的靜態塊的例子。在這個例子中,我們對JDBC進行了初始化。

Scala中的Object就相當於Java中靜態塊。

Object對象的應用

u 單例對象

u 使用應用程序對象:可以省略main方法;需要從父類App繼承。

7Scala中的apply方法

遇到如下形式的表達式時,apply方法就會被調用:

Object(參數1,參數2,......,參數N)

通常,這樣一個apply方法返回的是伴生類的對象;其作用是為了省略new關鍵字

Objectapply方法舉例:

8Scala中的繼承

ScalaJava一樣,使用extends關鍵字擴展類。

l 案例一:Employee類繼承Person

l 案例二:在子類中重寫父類的方法

l 案例三:使用匿名子類

l 案例四:使用抽象類。抽象類中包含抽象方法,抽象類只能用來繼承。

l 案例五:使用抽象字段。抽象字段就是一個沒有初始值的字段

9Scala中的trait(特質)

trait就是抽象類trait跟抽象類最大的區別:trait支持多重繼承

10、包的使用

Scala中包的定義和使用:

u 包的定義

u 包的引入:Scala中依然使用import作為引用包的關鍵字,例如

u 而且Scala中的import可以寫在任意地方

11、包對象

包可以包含類、對象和特質,但不能包含函數或者變量的定義。很不幸,這是Java虛擬機的局限。

把工具函數或者常量添加到包而不是某個Utils對象,這是更加合理的做法。Scala中,包對象的出現正是為了解決這個局限。

Scala中的包對象:常量,變量,方法,類,對象,trait(特質)

12Scala中的文件訪問

l 讀取行

l 讀取字符

其實這裏的source就指向了這個文件中的每個字符。

l URL或其他源讀取:註意指定字符集UTF-8

l 讀取二進制文件:Scala中並不支持直接讀取二進制,但可以通過調用JavaInputStream來進行讀入。

l 寫入文本文件

三、Scala語言的函數式編程

1Scala中的函數

Scala中,函數是“頭等公民”,就和數字一樣。可以在變量中存放函數,即:將函數作為變量的值(值函數)

2、匿名函數

3、帶函數參數的函數,即:高階函數

示例1

*)首先,定義一個最普通的函數

*)再定義一個高階函數

*)分析這個高階函數調用的過程

示例2

在這個例子中,首先定義了一個普通的函數mytest,然後定義了一個高階函數myFunctionmyFunction接收三個參數:第一個f是一個函數參數,第二個是x,第三個是y。而f是一個函數參數,本身接收兩個Int的參數,返回一個Int的值。

4、閉包

就是函數的嵌套,即:在一個函數定義中,包含另外一個函數的定義;並且在內函數中可以訪問外函數中的變量

測試上面的函數:

5、柯裏化:Currying

柯裏化函數(Curried Function)是把具有多個參數的函數轉換為一條函數鏈,每個節點上是單一參數。

一個簡單的例子:

6、高階函數示例

示例1

示例2

示例3

示例4

示例5

在這個例子中,可以被2整除的被分到一個分區;不能被2整除的被分到另一個分區。

示例6

示例7

示例8

在這個例子中,分為兩步:

(1)(1,2,3)(4,5,6)這兩個集合合並成一個集合

(2)再對每個元素乘以2

四、Scala中的集合

1、可變集合和不可變集合

l 可變集合

l 不可變集合:

n 集合從不改變,因此可以安全地共享其引用。

n 甚至是在一個多線程的應用程序當中也沒問題。

集合的操作:

2、列表

l 不可變列表(List

不可變列表的相關操作:

l 可變列表(LinkedList):scala.collection.mutable

3、序列

常用的序列有:VectorRange

u VectorArrayBuffer的不可變版本,是一個帶下標的序列

u Range表示一個整數序列

4、集(Set)和集的操作

l 集Set是不重復元素的集合

l 和列表不同,集並不保留元素插入的順序。默認以Hash集實現

示例1:創建集

示例2:集的操作

5、模式匹配

Scala有一個強大的模式匹配機制,可以應用在很多場合:

u switch語句

u 類型檢查

Scala還提供了樣本類(case class),對模式匹配進行了優化

模式匹配示例:

l 更好的switch

l Scala的守衛

l 模式匹配中的變量

l 類型模式

l 匹配數組和列表

6、樣本類(CaseClass)

簡單的來說,Scalacase class就是在普通的類定義前加case這個關鍵字,然後你可以對這些類來模式匹配。

case class帶來的最大的好處是它們支持模式識別。

首先,回顧一下前面的模式匹配:

其次,如果我們想判斷一個對象是否是某個類的對象,跟Java一樣可以使用isInstanceOf

下面這個好像有點問題

最後,在Scala中有一種更簡單的方式來判斷,就是case class

註意:需要在class前面使用case關鍵字。

五、Scala語言的高級特性

1、什麽是泛型類

Java或者C++一樣,類和特質可以帶類型參數。在Scala中,使用方括號來定義類型參數

測試程序:

2、什麽是泛型函數

函數和方法也可以帶類型參數。和泛型類一樣,我們需要把類型參數放在方法名之後。

註意:這裏的ClassTag是必須的,表示運行時的一些信息,比如類型。

3Upper Bounds Lower Bounds

類型的上界和下界,是用來定義類型變量的範圍。它們的含義如下:

l S <: T

這是類型上界的定義。也就是S必須是類型T的子類(或本身,自己也可以認為是自己的子類。

u U >: T

這是類型下界的定義。也就是U必須是類型T的父類(或本身,自己也可以認為是自己的父類)

l 一個簡單的例子:

l 一個復雜一點的例子(上界):

l 再來看一個例子:

4、視圖界定(View bounds

它比 <: 適用的範圍更廣,除了所有的子類型,還允許隱式轉換過去的類型。用 <% 表示。盡量使用視圖界定,來取代泛型的上界,因為適用的範圍更加廣泛。

示例:

l 上面寫過的一個列子。這裏由於T的上界是String,當我們傳遞100200的時候,就會出現類型不匹配。

l 但是100200是可以轉成字符串的,所以我們可以使用視圖界定讓addTwoString方法接收更廣泛的數據類型,即:字符串及其子類、可以轉換成字符串的類型

註意:使用的是 <%

l 但實際運行的時候,會出現錯誤:

這是因為:Scala並沒有定義如何將Int轉換成String的規則,所以要使用視圖界定,我們就必須創建轉換的規則。

l 創建轉換規則

l 運行成功

5、協變和逆變

l 協變:

Scala的類或特征的範型定義中,如果在類型參數前面加入+符號,就可以使類或特征變為協變了。

u 逆變:

在類或特征的定義中,在類型參數之前加上一個-符號,就可定義逆變範型類和特征了。

總結一下:Scala的協變:泛型變量的值可以是本身類型或者其子類的類型

Scala的逆變:泛型變量的值可以是本身類型或者其父類的類型

6、隱式轉換函數

所謂隱式轉換函數指的是以implicit關鍵字申明的帶有單個參數的函數。

l 前面講視圖界定時候的一個例子:

l 再舉一個例子:我們把Fruit對象轉換成了Monkey對象

7、隱式參數

使用implicit申明的函數參數叫做隱式參數。我們也可以使用隱式參數實現隱式的轉換

8、隱式類

所謂隱式類: 就是對類增加implicit 限定的類,其作用主要是對類的功能加強

scala的簡介安裝與基礎語法