變量
聲明變量
val/var 變量標(biāo)識(shí):變量類(lèi)型 = 初始值
其中
- Val表示的是不可改變的變量
- Var表示的是可以重新賦值的變量
Notice:
變量寫(xiě)在變量名后面,且不用寫(xiě)分號(hào)
語(yǔ)法格式
val name: String = "hello world"
var age:Int = 18
使用Scala中的類(lèi)型推導(dǎo)
Scala比Java語(yǔ)言更加簡(jiǎn)潔,類(lèi)似于Js,類(lèi)型可以被變量自動(dòng)根據(jù)等號(hào)后面的值來(lái)推導(dǎo)
語(yǔ)法格式
val name = "leon"
//可以自動(dòng)推導(dǎo)出name的類(lèi)型為String,不用再手動(dòng)添加
惰性賦值
類(lèi)似于懶加載,變量不會(huì)一次性全部加載到JVM的內(nèi)存中,可以提高運(yùn)行效率
語(yǔ)法格式
lazy val/var 變量名 = 表達(dá)式
lazy val sql =
"""insert overwrite table adm.itcast_adm_personas 19
| select | a.user_id, .... | left join gdm.itcast_gdm_user_buy_category c on a.user_id=c.user_id | left join gdm.itcast_gdm_user_visit d on a.user_id=d.user_id;"""
sql: String = <lazy>
字符串
使用字符串
語(yǔ)法格式
val/var 變量名 = “字符串”
有一個(gè)人的名字叫"hadoop",請(qǐng)打印他的名字以及名字的長(zhǎng)度。
val name = "liming"
println(name + name.length)
//打印"liming6"
使用插值表達(dá)式
語(yǔ)法格式
val/var 變量名 = s"${變量/表達(dá)式}字符串"
Tips:
- 在定義字符串之前添加 s
- 在字符串中,可以使用 ${} 來(lái)引用變量或者編寫(xiě)表達(dá)式
請(qǐng)定義若干個(gè)變量,分別保存:"zhangsan"、30、"male",定義一個(gè)字符串,保存這些信息。
打印輸出:name=zhangsan, age=30, sex=male
scala> val name = "zhangsan"
name: String = zhangsan
scala> val age = 30
age: Int = 30
scala> val sex = "male"
sex: String = male
scala> val info = s"name=${name}, age=${age}, sex=${sex}"
info: String = name=zhangsan, age=30, sex=male
scala> println(info)
name=zhangsan, age=30, sex=male
使用三引號(hào)
語(yǔ)法
val/var 變量名 = """字符串1
字符串2"""
定義一個(gè)字符串,保存以下SQL語(yǔ)句
select
*
from
t_user
where
name = "zhangsan"
val sql = """select
| *
| from
| t_user
| where
| name = "zhangsan""""
println(sql)
數(shù)據(jù)類(lèi)型與操作符
基本數(shù)據(jù)類(lèi)型
| 基礎(chǔ)類(lèi)型 | 類(lèi)型說(shuō)明 |
|---|---|
| Byte | 8位帶符號(hào)整數(shù) |
| Short | 16位帶符號(hào)整數(shù) |
| Int | 32位帶符號(hào)整數(shù) |
| Long | 64位帶符號(hào)整數(shù) |
| Char | 16位無(wú)符號(hào)Unicode字符 |
| String | Char類(lèi)型的序列(字符串) |
| Float | 32位單精度浮點(diǎn)數(shù) |
| Double | 64位雙精度浮點(diǎn)數(shù) |
| Boolean | true或false |
Tips:
- scala中所有的類(lèi)型都使用大寫(xiě)字母開(kāi)頭
- 整形使用 Int 而不是Integer
- scala中定義變量可以不寫(xiě)類(lèi)型,讓scala編譯器自動(dòng)推斷
操作符
| 類(lèi)別 | 操作符 |
|---|---|
| 算術(shù)運(yùn)算符 | +、-、*、/ |
| 關(guān)系運(yùn)算符 | >、<、==、!=、>=、<= |
| 邏輯運(yùn)算符 | &&、|| 、! |
| 位運(yùn)算符 | &、||、^ 、<<、>> |
Tips
scala中沒(méi)有,++、--運(yùn)算符-
與Java不一樣,在scala中,可以直接使用 == 、 != 進(jìn)行比較,它們與 equals 方法表示一
致。而比較兩個(gè)對(duì)象的引用值,使用
eq
有一個(gè)字符串"abc",再創(chuàng)建第二個(gè)字符串,值為:在第一個(gè)字符串后拼接一個(gè)空字符串。
然后使用比較這兩個(gè)字符串是否相等、再查看它們的引用值是否相等。
val str1 = "abc"
val str2 = str1 + ""
str1 == str2 //true
str1.eq(str2) //false
scala類(lèi)型層次結(jié)構(gòu)

| 類(lèi)型 | 說(shuō)明 |
|---|---|
| Any | 所有類(lèi)型的父類(lèi),,它有兩個(gè)子類(lèi)AnyRef與AnyVal |
| AnyVal | 所有數(shù)值類(lèi)型的父類(lèi) |
| AnyRef | 所有對(duì)象類(lèi)型(引用類(lèi)型)的父類(lèi) |
| Unit | 表示空,Unit是AnyVal的子類(lèi),它只有一個(gè)的實(shí)例() 它類(lèi)似于Java中的void,但scala要比Java更加面向?qū)ο?/td> |
| Null | Null是AnyRef的子類(lèi),也就是說(shuō)它是所有引用類(lèi)型的子類(lèi)。它的實(shí)例是null 可以將null賦值給任何對(duì)象類(lèi)型 |
| Nothing | 所有類(lèi)型的子類(lèi) 不能直接創(chuàng)建該類(lèi)型實(shí)例,某個(gè)方法拋出異常時(shí),返回的就是Nothing類(lèi)型因?yàn)镹othing是所有類(lèi)的子類(lèi),那么它可以賦值為任何類(lèi)型 |
條件表達(dá)式
Tips:
- 在scala中,條件表達(dá)式也是有返回值的
- 在scala中,沒(méi)有三元表達(dá)式,可以使用if表達(dá)式替代三元表達(dá)式
定義一個(gè)變量sex,再定義一個(gè)result變量,如果等于male,result等于1,如果result等于0
scala> val sex = "male"
sex: String = male
scala> val result = if(sex == "male") 1 else 0
result: Int = 1
塊表達(dá)式
scala中,使用{}表示一個(gè)塊表達(dá)式
和if表達(dá)式一樣,塊表達(dá)式也是有值的
值就是最后一個(gè)表達(dá)式的值
scala> val a = {
| println("1 + 1")
| 1 + 1
| }
循環(huán)
for
? 語(yǔ)法
for(i <- 表達(dá)式/數(shù)組/集合) {
// 表達(dá)式
}
- 使用for表達(dá)式打印1-10的數(shù)字
//先定義一個(gè)nums
scala> val nums = 1.to(10)
nums: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
//然后再打印for循環(huán)
scala> for(i <- nums) println(i)
- 中綴法
// 中綴調(diào)用法
scala> for(i <- 1 to 10) println(i)
嵌套循環(huán)
? 使用for表達(dá)式,打印以下字符
*****
*****
*****
步驟
是否for表達(dá)式打印3行,5列星星
每打印5個(gè)星星,換行
for(i <- 1 to 3; j <- 1 to 5) {print("*");if(j == 5) println("")}
scala中可以把嵌套寫(xiě)成在一個(gè)括號(hào)中執(zhí)行。然后后面接條件表達(dá)式
守衛(wèi)
? for表達(dá)式中,可以添加if判斷語(yǔ)句,這個(gè)if判斷就稱(chēng)之為守衛(wèi)。我們可以使用守衛(wèi)讓for表達(dá)式更簡(jiǎn)
潔。
語(yǔ)法
for(i <- 表達(dá)式/數(shù)組/集合 if 表達(dá)式) {
? // 表達(dá)式
}
使用for表達(dá)式打印能夠整除3的數(shù)字
// 添加守衛(wèi),打印能夠整除3的數(shù)字
for(i <- 1 to 10 if i % 3 == 0) println(i)
for推導(dǎo)式
將來(lái)可以使用for推導(dǎo)式生成一個(gè)新的集合(一組數(shù)據(jù))
-
在for循環(huán)體中,可以使用yield表達(dá)式構(gòu)建出一個(gè)集合,我們把使用yield的for表達(dá)式稱(chēng)之為推
導(dǎo)式
生成一個(gè)10、20、30...100的集合
// for推導(dǎo)式:for表達(dá)式中以yield開(kāi)始,該for表達(dá)式會(huì)構(gòu)建出一個(gè)集合
val v = for(i <- 1 to 10) yield i * 10
while循環(huán)
scala中while循環(huán)和Java中是一致的
打印1-10的數(shù)字
scala> var i = 1 i:
Int = 1
scala> while(i <= 10) {
| println(i)
| i = i+1
| }
方法
基本定義
? 一個(gè)類(lèi)可以有自己的方法,scala中的方法和Java方法類(lèi)似。但scala與Java定義方法的語(yǔ)法是不一
樣的,而且scala支持多種調(diào)用方式。
語(yǔ)法設(shè)置
def methodName (參數(shù)名:參數(shù)類(lèi)型, 參數(shù)名:參數(shù)類(lèi)型) : [return type] = {
? // 方法體:一系列的代碼
}
Tips:
- 參數(shù)列表的參數(shù)類(lèi)型不能省略
- 返回值類(lèi)型可以省略
- 返回值可以不寫(xiě)return,默認(rèn)就是{}塊表達(dá)式的值
示例
定義一個(gè)方法,實(shí)現(xiàn)兩個(gè)整形數(shù)值相加,返回相加后的結(jié)果
調(diào)用該方法
scala> def add(x:Int, y:Int):Int = x * y
m1: (x: Int, y: Int)Int
scala> add(1,2)
res10: Int = 2
方法參數(shù)
? scala中的方法參數(shù),使用比較靈活。它支持以下幾種類(lèi)型的參數(shù):
- 默認(rèn)參數(shù)
- 帶名參數(shù)
- 變長(zhǎng)參數(shù)
默認(rèn)參數(shù)
? 在定義方法時(shí)可以給參數(shù)定義一個(gè)默認(rèn)值。
示例
定義一個(gè)計(jì)算兩個(gè)值相加的方法,這兩個(gè)值默認(rèn)為0
調(diào)用該方法,不傳任何參數(shù)
// x,y帶有默認(rèn)值為0
def add(x:Int = 0, y:Int = 0) = x + y
add()
帶名參數(shù)
? 在調(diào)用方法時(shí),可以指定參數(shù)的名稱(chēng)來(lái)進(jìn)行調(diào)用。
示例
定義一個(gè)計(jì)算兩個(gè)值相加的方法,這兩個(gè)值默認(rèn)為0
調(diào)用該方法,只設(shè)置第一個(gè)參數(shù)的值
def add(x:Int = 0, y:Int = 0) = x + y
add(x=1)
變長(zhǎng)參數(shù)
? 如果方法的參數(shù)是不固定的,可以定義一個(gè)方法的參數(shù)是變長(zhǎng)參數(shù)。
語(yǔ)法格式:
def 方法名(參數(shù)名:參數(shù)類(lèi)型*):返回值類(lèi)型 = {
? 方法體
}
Tips:
- 在參數(shù)類(lèi)型后面加一個(gè) * 號(hào),表示參數(shù)可以是0個(gè)或者多個(gè)
示例
定義一個(gè)計(jì)算若干個(gè)值相加的方法
調(diào)用方法,傳入以下數(shù)據(jù):1,2,3,4,5
scala> def add(num:Int*) = num.sum
add: (num: Int*)Int
scala> add(1,2,3,4,5)
res1: Int = 15
方法返回值類(lèi)型推斷
? scala定義方法可以省略返回值,由scala自動(dòng)推斷返回值類(lèi)型。這樣方法定義后更加簡(jiǎn)潔。
示例
使用類(lèi)型推斷重新定義上面的add方法
scala> def add(x:Int, y:Int) = x + y
add: (x: Int, y: Int)Int
scala> add(1,2)
res12: Int = 3
方法調(diào)用方式
后綴調(diào)用法
語(yǔ)法
對(duì)象名.方法名(參數(shù))
示例
使用后綴法 Math.abs 求絕對(duì)值
scala> Math.abs(-1)
res3: Int = 1
中綴調(diào)用法
語(yǔ)法
對(duì)象名 方法名 參數(shù)
例如 : 1 to 10
示例
使用中綴法 Math.abs 求絕對(duì)值
scala> Math abs -1
res4: Int = 1
花括號(hào)調(diào)用法
語(yǔ)法
Math.abs{
? // 表達(dá)式1
? // 表達(dá)式2
}
示例
使用花括號(hào)調(diào)用法 Math.abs 求絕對(duì)值
scala> Math.abs{-10}
res13: Int = 10
無(wú)括號(hào)調(diào)用法
如果方法沒(méi)有參數(shù),可以省略方法名后面的括號(hào)
示例
- 定義一個(gè)無(wú)參數(shù)的方法,打印"hello"
- 使用無(wú)括號(hào)調(diào)用法調(diào)用該方法
def m3()=println("hello")
m3()
函數(shù)
scala支持函數(shù)式編程,將來(lái)編寫(xiě)Spark/Flink程序中,會(huì)大量經(jīng)常使用到函數(shù)
定義函數(shù)
語(yǔ)法
val 函數(shù)變量名 = (參數(shù)名:參數(shù)類(lèi)型, 參數(shù)名:參數(shù)類(lèi)型....) => 函數(shù)體
Tips:
- 函數(shù)是一個(gè)對(duì)象(變量)
- 類(lèi)似于方法,函數(shù)也有輸入?yún)?shù)和返回值
- 函數(shù)定義不需要使用 def 定義
- 無(wú)需指定返回值類(lèi)型
示例
定義一個(gè)兩個(gè)數(shù)值相加的函數(shù)
調(diào)用該函數(shù)
scala> val add = (x:Int, y:Int) => x + y
add: (Int, Int) => Int = <function2>
scala> add(1,2)
res3: Int = 3
方法和函數(shù)的區(qū)別
方法是隸屬于類(lèi)或者對(duì)象的,在運(yùn)行時(shí),它是加載到JVM的方法區(qū)中
可以將函數(shù)對(duì)象賦值給一個(gè)變量,在運(yùn)行時(shí),它是加載到JVM的堆內(nèi)存中
-
函數(shù)是一個(gè)對(duì)象,繼承自FunctionN,函數(shù)對(duì)象有apply,curried,toString,tupled這些方
法。方法則沒(méi)有
示例
方法無(wú)法賦值給變量
scala> def add(x:Int,y:Int)=x+y
add: (x: Int, y: Int)Int
scala> val a = add
<console>:12: error: missing argument list for method add Unapplied methods are only converted to functions when a function type is expected. You can make this conversion explicit by writing `add _` or `add(_,_)` instead of `add`.
val a = add
方法轉(zhuǎn)換為函數(shù)
- 有時(shí)候需要將方法轉(zhuǎn)換為函數(shù),作為變量傳遞,就需要將方法轉(zhuǎn)換為函數(shù)
- 使用
_即可將方法轉(zhuǎn)換為函數(shù)
scala> def add(x:Int,y:Int)=x+y
add: (x: Int, y: Int)Int scala>
val a = add _
a: (Int, Int) => Int = <function2>