Scala基礎
簡介
Scala是運行在 JVM 上的多範式編程語言,同時支持面向對象和面向函數編程,隨着Spark和Kafka這樣基於Scala的大數據框架的興起,Scala逐步成爲大數據行業編程的首選。
Scala的優勢主要是:
- 開發大數據應用程序(Spark程序、Flink程序)
- 表達能力強,一行代碼抵得上Java多行,開發速度快
- 兼容Java,可以訪問龐大的Java類庫
環境
- Scala程序運行在JVM之上,所以必須要有Java運行環境,Scala才能正確執行
- 安裝JDK 1.8 版本,並配置好環境變量,注意:版本一定是JDK8,雖然現在已經到了JDK13
Java SE 8就是Java8,或者jdk1.8
- 下載Scala SDK,並配置環境變量
- 編譯器仍然使用IDEA,需要安裝Scala插件
插件在官網下載,要對應你的IDEA版本
插件的安裝:【settings——plugins——Install Plugin From Disk】選擇下載的壓縮包即可!
- 使用IDEA新建工程,選擇scala
語法
變量聲明
val/var 變量名稱:變量類型 = 初始值
val
定義的是不可重新賦值的變量(值不可修改)var
定義的是可重新賦值的變量(值可以修改)- 如果變量類型不顯式聲明則會自行推斷
- scala的語句最後不需要添加分號
惰性變量
- scala中使用關鍵字
lazy
來定義惰性變量,實現延遲加載(懶加載) - 惰性變量只能是不可變變量,並且只有在調用時,纔會去實例化這個變量
數據類型
基礎類型 | 類型說明 |
---|---|
Byte | 8位帶符號整數 |
Short | 16位帶符號整數 |
Int | 32位帶符號整數 |
Long | 64位帶符號整數 |
Char | 16位無符號Unicode字符 |
String | Char類型的序列(字符串) |
Float | 32位單精度浮點數 |
Double | 64位雙精度浮點數 |
Boolean | true或false |
- scala中所有的類型都使用大寫字母開頭
- 類型說明:
類型 | 說明 |
---|---|
Any | 所有類型的父類,,它有兩個子類AnyRef與AnyVal |
AnyVal | 所有數值類型的父類 |
AnyRef | 所有對象類型(引用類型)的父類 |
Unit | 表示空,Unit是AnyVal的子類,它只有一個的實例(),它類似於Java中的void,但scala要比Java更加面向對象 |
Null | Null是AnyRef的子類,也就是說它是所有引用類型的子類。它的實例是null, 可以將null賦值給任何對象類型 |
Nothing | 所有類型的子類不能直接創建該類型實例,某個方法拋出異常時,返回的就是Nothing類型,因爲Nothing是所有類的子類,那麼它可以賦值爲任何類型 |
條件表達式
- scala中的表達式都是有值的,可以理解爲表達式是scala中的常用單元或“數據類型”
val x =1
val z = if(x>1) 1 else "error"
print(z) // error
塊表達式
- 塊表達式也是有值的
val result = {
val x=0
val y = x+10
val z = y+"-hello"
val m = z+"-kaikeba"
"over" // 最後的over賦給result
}
for循環
- 和go語言的語法很相似
val nums= 1 to 10
for(i <- nums) println(i)
// 雙重for循環
for(i <- 1 to 3; j <- 1 to 3) println(i*10+j)
// 乘法表
for(i <- 1 to 9; j <- 1 to i){
print(i+"*"+j+"="+i*j+"\t")
if(i==j){
println()
}
}
- 守衛:for循環中的if判斷
for(i <- 1 to 10 if i >5) println(i)
- 推導式:使用yield的for表達式,可以構建出一個集合
val v = for(i <- 1 to 5) yield i * 10
println(v) // Vector(10, 20, 30, 40, 50)
方法
def methodName (參數名:參數類型, 參數名:參數類型) : [return type] = {
// 方法體
}
- 參數列表的參數類型不能省略
- 返回值類型可以省略,根據方法體的最後一行值確定
- 在定義方法時可以給參數定義一個默認值
- 調用方法時,可以指定參數的名稱傳值
def add(a:Int,b:Int) = {
a+b
"value"
}
print(add(1,2)) // value
- 如果定義遞歸方法,不能省略返回值類型
def m1(x:Int):Int={
if (x==1) 1
else x*m1(x-1)
}
print(m1(10)) // 3628800
- 變長參數:
def add(num:Int*) = num.sum
print(add(1,2,3,4)) // 10
函數
- scala支持函數式編程,編寫Spark/Flink程序會大量使用到函數
val 函數變量名 = (參數名:參數類型, 參數名:參數類型…) => 函數體
- 函數是一個對象(變量)
- 一個函數沒有賦予一個變量,則稱爲匿名函數
- 無需指定返回值類型
val add = (x:Int, y:Int) => x + y
print(add(2,3))
數組
- scala中,有兩種數組,一種是定長數組,另一種是變長數組
- 定長數組
// 通過指定長度定義數組
val/var 變量名 = new Array[元素類型](數組長度)
// 用元素直接初始化數組
val/var 變量名 = Array(元素1, 元素2, 元素3…)
val a = new Array[Int](10) // 長度爲10的數組
a(0) = 666
print(a(0)) // 0
val b = Array("hadoop","spark","hive") // 初始化
print(b.length) // 3
- 變長數組
創建變長數組,需要提前導入ArrayBuffer類:
import scala.collection.mutable.ArrayBuffer
- 使用
+=
添加元素 - 使用
-=
刪除元素 - 使用
++=
追加一個數組到變長數組
var c = ArrayBuffer[Int](666,888)
c += 999 // 追加
c -= 888 // 刪除
c ++= a // 追加一個變長數組
print(c) // ArrayBuffer(666, 999, 666, 0, 0, 0, 0, 0, 0, 0, 0, 0)
- 遍歷數組
for(i <- a)println(i)
for(i <- 0 to a.length -1 )println(a(i))
for(i <- 0 to a.length -1 )println(a(i)) // 0 until n ——生成一系列的數字,包含0,不包含n
- 數組常見操作
- 求和——sum方法
- 求最大值——max方法
- 求最小值——min方法
- 排序——sorted方法
array.sum
array.max
array.min
array.sorted
array.sorted.reverse
元組
- 元組可以用來包含一組不同類型的值
val/var 元組變量名稱 = (元素1, 元素2, 元素3…)
val/var 元組變量名稱 = 元素1->元素2 // 只有兩個元素時
val a = (1, "張三", 20, "北京市")
val b = 1->2
// 訪問元組中的元素_1、_2、_3....
print(a._1) // 1
Map
- Map可以稱之爲映射。它是由鍵值對組成的集合,scala當中的Map集合與java當中的Map類似
val/var map = Map(鍵->值, 鍵->值, 鍵->值…) // 推薦,可讀性更好
- 不可變Map:
val map1 = Map("zhangsan"->30, "lisi"->40)
print(map1("zhangsan")) // 30
println(map1.getOrElse("wangwu", -1)) // 如果沒有key,返回-1而不是保錯
- 可變Map
import scala.collection.mutable.Map // 需要導包,語法相同
map1("zhangsan") = 50
map3 += ("wangwu" ->35) // 添加key-value
map3 -= "wangwu" // 刪除key-value
println(map3.keys) // Set(zhangsan, wangwu)
println(map3.keySet) // Set(zhangsan, wangwu)
println(map3.values) // HashMap(50, 40)
// 遍歷
for((k,v) <- map3) println(k+" -> "+v)
Set
- Set是代表沒有重複元素的集合
- Set沒有順序
- 不可變集合
//創建一個空的不可變集
val/var 變量名 = Set[類型]()
//給定元素來創建一個不可變集
val/var 變量名 = Set[類型](元素1, 元素2, 元素3…)
- 可變集合
必須導入:import scala.collection.mutable.Set
創建方法和不可變集合相同
val set = Set(1,1,2,3,4,5)
println(set.size)
for(i <- set) println(i)
set += 6 //添加元素
set += (6,7,8,9) // 添加多個元素
println(set)
set -= 1 // 刪除一個元素
set -= (9,10) // 刪除多個元素
println(set)
set --= Set(2,3) // 刪除一個集合
println(set)
set ++= Set(6,7,8) // 拼接兩個集合
println(set)
println(set & Set(3,6))//求2個Set集合的交集
set.remove(8)
println(set)
List
- List是scala中最重要的、也是最常用的數據結構
- 有序、可重複
- 不可變列表:
val/var 變量名 = List(元素1, 元素2, 元素3...)
//使用 Nil 創建一個不可變的空列表
val/var 變量名 = Nil
//使用 :: 方法創建一個不可變列表
val/var 變量名 = 元素1 :: 元素2 :: Nil
- 可變列表
必須導入 :import scala.collection.mutable.ListBuffer
val list4 = ListBuffer[Int]()
val list = ListBuffer(1,2,3,4) // 帶初始元素
println(list(0)) // 獲取第一個元素
println(list.head) // 獲取第一個元素
println(list.tail) // 獲取除了第一個元素外其他元素組成的列表
println(list += 5) // 添加單個元素
println(list ++= List(6,7)) // 添加一個不可變的列表
println(list ++= ListBuffer(8,9)) //添加一個可變的列表(刪除同樣)
println(list.isEmpty) // 列表是否爲空
list.toList //根據可變的列表生成不可變列表,原列表不變
list.toArray //根據可變的列表生成不可變數組,原列表不變
小結
這裏總結了scala的基本語法,由於主要用於函數式編程,需要形成特殊的語法習慣,熟能生巧!
更加詳細的介紹可以查看教程,很多細節不必死記硬背,只需要大致總結即可,比如數組、映射、集合、列表都有可變和不可變之分等,隨着使用的深入瞭解原理纔是目的。
要抓主要矛盾,解決主要矛盾,作爲大數據編程的利器,下一節會介紹到Spark/Flink的大量業務代碼都會使用到的函數式編程!