目錄
-
變量
定義變量
val/var 變量標識:變量類型 = 初始值
val:定義的是不可重新賦值的變量
var:定義的是可重新賦值的變量
定義一個變量
val name:String = "tom"
使用類型推斷來定義變量
scala可以自動根據變量的值來自動推斷變量的類型,這樣編寫代碼更加簡潔
惰性賦值
在企業的大數據開發中,有時候會編寫非常複雜的SQL語句,這些SQL語句可能有幾百行甚至上千行。這些SQL語句,如果直接加載到JVM中,會有很大的內存開銷。當有一些變量保存的數據較大時,但是不需要馬上加載到JVM內存。可以使用惰性賦值來提高效率
語法格式:
lazy val/var 變量名 = 表達式
-
字符串
scala提供多種定義字符串的方式,將來我們可以根據需要來選擇最方便的定義方式。
1.使用雙引號
2.使用插值表達式
3.使用三引號
使用雙引號
語法:
val/var 變量名 = “字符串”
使用插值表達式
在定義字符串之前添加s
在字符串中,可以使用${}來引用變量或者編寫表達式
語法:
val/var 變量名 = s"${變量/表達式}字符串"
使用三引號
如果有大段的文本需要保存,就可以使用三引號來定義字符串。例如:保存一大段的SQL語句。三個引號中間的所有字符串都將作爲字符串的值。
語法:
val/var 變量名 = """字符串1 字符串2"""
-
數據類型
基礎類型 |
類型說明 |
Byte |
8位帶符號整數 |
Short |
16位帶符號整數 |
Int |
32位帶符號整數 |
Long |
64位帶符號整數 |
Char |
16位無符號Unicode字符 |
String |
Char類型的序列(字符串) |
Float |
32位單精度浮點數 |
Double |
64位雙精度浮點數 |
Boolean |
true或false |
- scala中所有的類型都使用大寫字母開頭
- 整形使用Int而不是Integer
- scala中定義變量可以不寫類型,讓scala編譯器自動推斷
-
運算符
類別 |
操作符 |
算術運算符 |
+、-、*、/ |
關係運算符 |
>、<、==、!=、>=、<= |
邏輯運算符 |
&&、|| 、! |
位運算符 |
&、、^、<<、>> |
1.scala中沒有,++、--運算符
2.與Java不一樣,在scala中,可以直接使用==、!=進行比較,它們與equals方法表示一致。而比較兩個對象的引用值,使用eq
-
scala類型層次結構
類型 |
說明 |
Any |
所有類型的父類,,它有兩個子類AnyRef與AnyVal |
AnyVal |
所有數值類型的父類 |
AnyRef |
所有對象類型(引用類型)的父類 |
Unit |
表示空,Unit是AnyVal的子類,它只有一個的實例() 它類似於Java中的void,但scala要比Java更加面向對象 |
Null |
Null是AnyRef的子類,也就是說它是所有引用類型的子類。 它的實例是null可以將null賦值給任何對象類型 |
Nothing |
所有類型的子類不能直接創建該類型實例,某個方法拋出異常時,返回的就是Nothing類型,因爲Nothing是所有類的子類,那麼它可以賦值爲任何類型 |
-
條件表達式
條件表達式就是if表達式,if表達式可以根據給定的條件是否滿足,根據條件的結果(真或假)決定執行對應的操作。scala條件表達式的語法和Java一樣。
有返回值的if
1.在scala中,條件表達式也是有返回值的
2.在scala中,沒有三元表達式,可以使用if表達式替代三元表達式
例:
val sex = "male"
val result = if(sex == "male") 1 else 0
塊表達式
1.scala中,使用{}表示一個塊表達式
2.和if表達式一樣,塊表達式也是有值的,就是最後一個表達式的值
val a = {
println("1 + 1")
1 + 1
}
-
for循環
在scala中,可以使用for和while,但一般推薦使用for表達式,因爲for表達式語法更簡潔
for表達式
語法:
for(i <- 表達式/數組/集合) { // 表達式 }
簡單循環
例:使用for表達式打印1-10的數字
val nums = 1.to(10)
for(i <- nums) println(i)
嵌套循環
for(i <- 1 to 3; j <- 1 to 5) {print("*");if(j == 5) println("")}
守衛
for表達式中,可以添加if判斷語句,這個if判斷就稱之爲守衛。我們可以使用守衛讓for表達式更簡潔
語法:
for(i <- 表達式/數組/集合 if 表達式) {
// 表達式
}
例:
// 添加守衛,打印能夠整除3的數字
for(i <- 1 to 10 if i % 3 == 0) println(i)
for推導式
在for循環體中,可以使用yield表達式構建出一個集合,我們把使用yield的for表達式稱之爲推導式
例:生成一個10、20、30...100的集合
// for推導式:for表達式中以yield開始,該for表達式會構建出一個集合
val v = for(i <- 1 to 10) yield i * 10
-
while循環
scala中while循環和Java中是一致的
例:打印1-10的數字
scala> var i = 1
i: Int = 1
scala> while(i <= 10) {
| println(i)
| i = i+1
| }
-
break和continue
1.scala中,沒有break/continue關鍵字
2.如果一定要使用break/continue,就需要使用scala.util.control包的Break類的breable和break方法
實現break
1.導入Breaks包import scala.util.control.Breaks._
2.使用breakable將for表達式包起來
3.for表達式中需要退出循環的地方,添加break()方法調用
例:使用for表達式打印1-100的數字,如果數字到達50,退出for表達式
// 導入scala.util.control包下的Break
import scala.util.control.Breaks._
breakable{
for(i <- 1 to 100) {
if(i >= 50) break()
else println(i)
}
}
實現continue
1.continue的實現與break類似,但有一點不同:
2.實現continue是用breakable{}將for表達式的循環體包含起來
例:打印1-100的數字,使用for表達式來遍歷,如果數字能整除10,不打印
// 導入scala.util.control包下的Break
import scala.util.control.Breaks._
for(i <- 1 to 100 ) {
breakable{
if(i % 10 == 0) break()
else println(i)
}
}
-
方法
一個類可以有自己的方法,scala中的方法和Java方法類似。但scala與Java定義方法的語法是不一樣的
定義方法
1.參數列表的參數類型不能省略
2.返回值類型可以省略,由scala編譯器自動推斷
3.返回值可以不寫return,默認就是{}塊表達式的值
語法:
def methodName (參數名:參數類型, 參數名:參數類型) : [return type] = {
// 方法體:一系列的代碼
}
例:定義一個方法,實現兩個整形數值相加,返回相加後的結果,調用該方法
scala> def add(a:Int, b:Int) = a + b
m1: (x: Int, y: Int)Int
scala> add(10,20)
res9: Int = 30
-
方法參數
scala中的方法參數,使用比較靈活。它支持以下幾種類型的參數:
1.默認參數
2.帶名參數
3.變長參數
默認參數
在定義方法時可以給參數定義一個默認值
例:
def add(x:Int = 10, y:Int = 20) = x + y
add()
帶名參數
在調用方法時,可以指定參數的名稱來進行調用
例:
def add(x:Int = 0, y:Int = 0) = x + y
add(x=1)
變長參數
如果方法的參數是不固定的,可以定義一個方法的參數是變長參數
語法:
def 方法名(參數名:參數類型*):返回值類型 = {
方法體
}
例:
def add(num:Int*) = num.sum
add(1,2,3,4,5)
-
方法調用方式
在scala中,有以下幾種方法調用方式
1.後綴調用法
2.中綴調用法
3.花括號調用法
4.無括號調用法
後綴調用法
語法:
對象名.方法名(參數)
例:使用後綴法Math.abs求絕對值
Math.abs(-1)
中綴調用法
語法:注意空格
對象名 方法名 參數
例:使用中綴法Math.abs求絕對值
Math abs -1
花括號調用法
語法:方法只有一個參數,才能使用花括號調用法
對象名.方法名{
// 表達式1
// 表達式2
}
例:使用花括號調用法Math.abs求絕對值
Math.abs{-10}
無括號調用法
語法:如果方法沒有參數,可以省略方法名後面的括號
方法名
例:定義一個無參數的方法,打印"hello",使用無括號調用法調用該方法
def m3()=println("hello")
m3()
-
返回值類型推斷
1.scala定義方法可以省略返回值,由scala自動推斷返回值類型。
2.定義遞歸方法,不能省略返回值類型
例:定義遞歸方法(求階乘)
def m2(x:Int) = {
| if(x<=1) 1
| else m2(x-1) * x
| }
-
函數
1.scala支持函數式編程,將來編寫Spark/Flink程序中,會大量使用到函數
2.函數是一個對象(變量)
3.類似於方法,函數也有輸入參數和返回值
4.函數定義不需要使用def定義
5.無需指定返回值類型
定義函數
語法:
val 函數變量名 = (參數名:參數類型, 參數名:參數類型....) => 函數體
例:
val add = (x:Int, y:Int) => x + y
add(1,2)
方法和函數的區別
1.方法是隸屬於類或者對象的,在運行時,它是加載到JVM的方法區中
2.可以將函數對象賦值給一個變量,在運行時,它是加載到JVM的堆內存中
3.函數是一個對象,繼承自FunctionN,函數對象有apply,curried,toString,tupled這些方法。方法則沒有
4.方法無法賦值給變量
方法轉換爲函數
1.有時候需要將方法轉換爲函數,作爲變量傳遞,就需要將方法轉換爲函數
2.使用_即可將方法轉換爲函數
例:
def add(x:Int,y:Int)=x+y
val a = add _
add(1,2)
-
數組
scala中,有兩種數組,一種是定長數組,另一種是變長數組
定長數組
1.定長數組指的是數組的長度是不允許改變的
2.數組的元素是可以改變的
3.在scala中,數組的泛型使用[]來指定
4.使用()來獲取元素
語法:
// 通過指定長度定義數組
val/var 變量名 = new Array[元素類型](數組長度)
// 用元素直接初始化數組
val/var 變量名 = Array(元素1, 元素2, 元素3...)
例:
val a = new Array[Int](100)
a(0) = 110
println(a(0))
變長數組
1.變長數組指的是數組的長度是可變的,可以往數組中添加、刪除元素
2.創建變長數組,需要提前導入ArrayBuffer類import scala.collection.mutable.ArrayBuffer
語法:
//創建空的ArrayBuffer變長數組
import scala.collection.mutable.ArrayBuffer
val/var a = ArrayBuffer[元素類型]()
//創建帶有初始元素的ArrayBuffer
import scala.collection.mutable.ArrayBuffer
val/var a = ArrayBuffer(元素1,元素2,元素3....)
例:定義一個長度爲0的整型變長數組
val a = ArrayBuffer[Int]()
例:定義一個包含"hadoop", "storm", "spark"元素的變長數組
val a = ArrayBuffer("hadoop", "storm", "spark")
變長數組添加/修改/刪除元素
1.使用+=添加元素
2.使用-=刪除元素
3.使用++=追加一個數組到變長數組
例:
// 定義變長數組
import scala.collection.mutable.ArrayBuffer
val a = ArrayBuffer("hadoop", "spark", "flink")
// 追加一個元素
a += "flume"
// 刪除一個元素
a -= "hadoop"
// 追加一個數組
a ++= Array("hive", "sqoop")
遍歷數組
1.0 until n:生成一系列的數字,包含0,不包含n
2.0 to n :包含0,也包含n
使用for表達式直接遍歷數組中的元素
val a = Array(1,2,3,4,5)
for(i<-a) println(i)
使用索引遍歷數組中的元素
val a = Array(1,2,3,4,5)
for(i <- 0 to a.length - 1) println(a(i))
數組常用算法
1.求和:sum
2.求最大值:max
3.求最小值:min
4.排序:sorted
val a = Array(1,2,3,4,5)
//求和
a.sum
//求最大值
a.max
//求最小值
a.min
//升序排序
a.sorted
//降序排序
a.sorted.reverse
-
元組
元組可以用來包含一組不同類型的值。元組的元素是不可變的。
定義元組
語法:
//使用括號來定義元組
val/var 元組 = (元素1, 元素2, 元素3....)
//使用箭頭來定義元組(元組只有兩個元素)
val/var 元組 = 元素1->元素2
例:
val a = ("zhangsan", 20)
val b = "zhangsan" -> 20
訪問元組
1.使用_1、_2、_3....來訪問元組中的元素,_1表示訪問第一個元素,依次類推
例:
val a = "zhangsan" -> "male"
a._1
-
列表
1.列表是scala中最重要的、也是最常用的數據結構
2.列表可以保存重複的值
3.列表有先後順序
4.在scala中,也有兩種列表,一種是不可變列表、另一種是可變列表
不可變列表
1.不可變集合都在immutable包中(默認導入)
語法:
val/var 變量名 = List(元素1, 元素2, 元素3...)
//使用Nil創建一個不可變的空列表
val/var 變量名 = Nil
//使用::方法創建一個不可變列表,使用::拼接方式來創建列表,必須在最後添加一個Nil
val/var 變量名 = 元素1 :: 元素2 :: Nil
例:
//創建一個不可變列表,存放以下幾個元素(1,2,3,4)
val a = List(1,2,3,4)
//使用Nil創建一個不可變的空列表
val a = Nil
//使用::方法創建列表,包含-2、-1兩個元素
val a = -2 :: -1 :: Nil
可變列表
1.可變列表就是列表的元素、長度都是可變的
2.要使用可變列表,先要導入import scala.collection.mutable.ListBuffer
3.可變集合都在mutable包中
語法:
//使用ListBuffer[元素類型]()創建空的可變列表
val/var 變量名 = ListBuffer[Int]()
//使用ListBuffer(元素1, 元素2, 元素3...)創建可變列表
val/var 變量名 = ListBuffer(元素1,元素2,元素3...)
例:
import scala.collection.mutable.ListBuffer
//創建空的整形可變列表
val a = ListBuffer[Int]()
//創建一個可變列表,包含以下元素:1,2,3,4
val a = ListBuffer(1,2,3,4)
可變列表操作
1.獲取元素(使用括號訪問(索引值))
2.添加元素(+=)
3.追加一個列表(++=)
4.更改元素(使用括號獲取元素,然後進行賦值)
5.刪除元素(-=)
6.轉換爲List(toList)
7.轉換爲Array(toArray)
例:
val a = ListBuffer(1,2,3,4)
//獲取0號索引的值
a(0)
//添加一個元素
a+=5
//追加一個列表
val b = ListBuffer(10,20,30)
a ++= b
//更改元素
a(0) = 111
//刪除元素
a -= 2
//轉換爲List(toList)
a.toList
//轉換爲Array(toArray)
a.toArray
列表常用操作
1.判斷列表是否爲空(isEmpty)
2.拼接兩個列表(++)
3.獲取列表的首個元素(head)和剩餘部分(tail)
4.反轉列表(reverse)
5.獲取前綴(take)、獲取後綴(drop)
6.扁平化(flaten)
7.拉鍊(zip)和拉開(unzip)
8.轉換字符串(toString)
9.生成字符串(mkString)
10.並集(union)
11.交集(intersect)
12.差集(diff)
例:
//判斷列表是否爲空
val a = List(1,2,3,4)
a.isEmpty
//拼接兩個列表
val a = List(1,2,3)
val b = List(4,5,6)
a ++ b
//獲取列表的首個元素和剩餘部分
val a = List(1,2,3)
a.head
a.tail
//反轉列表
val a = List(1,2,3)
a.reverse
//獲取列表前綴和後綴
val a = List(1,2,3,4,5)
a.take(3)
a.drop(3)
//扁平化(壓平) 扁平化表示將列表中的列表中的所有元素放到一個列表中
val a = List(List(1,2), List(3), List(4,5))
a.flatten
//拉鍊與拉開
//拉鍊:使用zip將兩個列表,組合成一個元素爲元組的列表
//拉開:將一個包含元組的列表,解開成包含兩個列表的元組
val a = List("zhangsan", "lisi", "wangwu")
val b = List(19, 20, 21)
a.zip(b)
res1.unzip
//轉換字符串 toString方法可以返回List中的所有元素
val a = List(1,2,3,4)
println(a.toString)
//生成字符串 mkString方法,可以將元素以分隔符拼接起來。默認沒有分隔符
val a = List(1,2,3,4)
a.mkString
a.mkString(":")
//並集 union表示對兩個列表取並集,不去重 可以調用distinct去重
val a1 = List(1,2,3,4)
val a2 = List(3,4,5,6)
a1.union(a2)
a1.union(a2).distinct
//交集 intersect表示對兩個列表取交集
val a1 = List(1,2,3,4)
val a2 = List(3,4,5,6)
a1.intersect(a2)
//差集 diff表示對兩個列表取差集 a1.diff(a2),表示獲取a1在a2中不存在的元素
val a1 = List(1,2,3,4)
val a2 = List(3,4,5,6)
a1.diff(a2)
-
Set
1.Set(集)是代表沒有重複元素的集合,元素不重複
2.不保證插入順序
3.scala中的集也分爲兩種,一種是不可變集,另一種是可變集。
不可變集
語法:
//創建一個空的不可變集
val/var 變量名 = Set[類型]()
//給定元素來創建一個不可變集
val/var 變量名 = Set(元素1, 元素2, 元素3...)
例:
//定義一個空的不可變集
val a = Set[Int]()
//定義一個不可變集,保存以下元素:1,1,3,2,4,8
val a = Set(1,1,3,2,4,8)
基本操作
1.獲取集的大小(size)
2.遍歷集(和遍歷數組一致)
3.刪除一個元素,生成一個Set(-)
4.添加一個元素,生成一個Set(+)
5.拼接兩個集,生成一個Set(++)
6.拼接集和列表,生成一個Set(++)
例:
// 創建集
val a = Set(1,1,2,3,4,5)
// 獲取集的大小
a.size
// 遍歷集
for(i <- a) println(i)
// 刪除一個元素
a - 1
//添加一個元素
a + 1
// 拼接兩個集
a ++ Set(6,7,8)
// 拼接集和列表
a ++ List(6,7,8,9)
可變集
可變集合不可變集的創建方式一致,只不過需要提前導入一個可變集類。手動導入:import scala.collection.mutable.Set
例:
import scala.collection.mutable.Set
val a = Set(1,2,3,4)
a += 5
a -= 1
-
映射(Map)
Map可以稱之爲映射。它是由鍵值對組成的集合。在scala中,Map也分爲不可變Map和可變Map
不可變Map
語法:
val/var map = Map(鍵->值, 鍵->值, 鍵->值...) // 推薦,可讀性更好
val/var map = Map((鍵, 值), (鍵, 值), (鍵, 值), (鍵, 值)...)
例:
val map = Map("zhangsan"->30, "lisi"->40)
val map = Map(("zhangsan", 30), ("lisi", 30))
//根據key獲取value
map("zhangsan")
可變Map
定義語法與不可變Map一致。但定義可變Map需要手動導入import scala.collection.mutable.Map
例:
val map = Map("zhangsan"->30, "lisi"->40)
Map基本操作
1.獲取值(map(key))
2.獲取所有key(map.keys)
3.獲取所有value(map.values)
4.遍歷map集合
5.找到指定鍵的值如果不存在返回指定值(getOrElse)
6.增加key,value對(+)
7.刪除key(-)
例:
val map = Map("zhangsan"->30, "lisi"->40)
//獲取zhagnsan的年齡
map("zhangsan")
//獲取所有的key
map.keys
//獲取所有的value
map.values
//遍歷打印所有的key value
for((x,y) <- map) println(s"${x} ${y}")
//獲取wangwu的年齡,如果wangwu不存在,則返回-1
map.getOrElse("wangwu", -1)
//新增一個學生:wangwu, 35
map += "wangwu"->35
//將lisi從可變映射中移除
map - "lisi"
-
iterator迭代器
1.scala針對每一類集合都提供了一個迭代器(iterator)用來迭代訪問集合
2.使用iterator方法可以從集合獲取一個迭代器
3.迭代器的兩個基本操作
4.hasNext——查詢容器中是否有下一個元素
5.next——返回迭代器的下一個元素,如果沒有,拋出NoSuchElementException
6.每一個迭代器都是有狀態的
7.迭代完後保留在最後一個元素的位置
8.再次使用則拋出NoSuchElementException
9.可以使用while或者for來逐個返回元素
例:
//定義一個列表,包含以下元素:1,2,3,4,5
var a = List(1,2,3,4,5)
//創建迭代器
val ite = a.iterator
//使用while循環和迭代器,遍歷打印該列表
while(ite.hasNext) {
println(ite.next)
}