柚子快報邀請碼778899分享:后端 Scala第五章節(jié)
柚子快報邀請碼778899分享:后端 Scala第五章節(jié)
Scala第五章節(jié)
scala總目錄
章節(jié)目標
掌握方法的格式和用法掌握函數(shù)的格式和用法掌握九九乘法表案例
1. 方法
1.1 概述
實際開發(fā)中, 我們需要編寫大量的邏輯代碼, 這就勢必會涉及到重復的需求. 例如: 求10和20的最大值, 求11和22的最大值, 像這樣的需求, 用來進行比較的邏輯代碼需要編寫兩次, 而如果把比較的邏輯代碼放到方法中, 只需要編寫一次就可以了, 這就是方法. scala中的方法和Java方法類似, 但scala與Java定義方法的語法是不一樣的。
1.2 語法格式
def 方法名(參數(shù)名:參數(shù)類型, 參數(shù)名:參數(shù)類型) : [return type] = {
//方法體
}
注意:
參數(shù)列表的參數(shù)類型不能省略返回值類型可以省略,由scala編譯器自動推斷返回值可以不寫return,默認就是{}塊表達式的值
1.3 示例
**需求: **
定義一個方法getMax,用來獲取兩個整型數(shù)字的最大值, 并返回結果(最大值).調用該方法獲取最大值, 并將結果打印到控制臺上.
參考代碼
方式一: 標準寫法
//1. 定義方法, 用來獲取兩個整數(shù)的最大值.
def getMax(a:Int, b:Int): Int = {
return if(a > b) a else b
}
//2. 調用方法, 獲取最大值.
val max = getMax(10, 20)
//3. 打印結果.
println("max: " + max)
方式二: 優(yōu)化版
//1. 定義方法, 用來獲取兩個整數(shù)的最大值.
def getMax(a:Int, b:Int) = if(a > b) a else b
//2. 調用方法, 獲取最大值.
val max = getMax(22, 11)
//3. 打印結果.
println("max: " + max)
1.4 返回值類型推斷
scala定義方法可以省略返回值的數(shù)據(jù)類型,由scala自動推斷返回值類型。這樣方法定義后更加簡潔。
注意: 定義遞歸方法,不能省略返回值類型
示例
定義遞歸方法, 求5的階乘.
步驟
定義方法factorial, 用來計算某個數(shù)字的階乘
規(guī)律: 1的階乘等于1, 其他數(shù)字的階乘為: n! = n * (n - 1)!
調用方法, 獲取5的階乘, 并將結果打印到控制臺上.
參考代碼
//1. 定義方法factorial, 用來計算某個數(shù)字的階乘
def factorial(n:Int):Int = if(n == 1) 1 else n * factorial(n - 1)
//2. 調用方法, 獲取5的階乘.
val result = factorial(5)
//3. 將結果打印到控制臺上.
println("result: " + result)
1.5 惰性方法
當記錄方法返回值的變量被聲明為lazy時, 方法的執(zhí)行將被推遲, 直到我們首次使用該值時, 方法才會執(zhí)行, 像這樣的方法, 就叫: 惰性方法.
注意:
Java中并沒有提供原生態(tài)的"惰性"技術, 但是可以通過特定的代碼結構實現(xiàn), 這種結構被稱之為: 懶加載(也叫延遲加載)lazy不能修飾var類型的變量.
使用場景:
打開數(shù)據(jù)庫連接
由于表達式執(zhí)行代價昂貴, 因此我們希望能推遲該操作, 直到我們確實需要表達式結果值時才執(zhí)行它
提升某些特定模塊的啟動時間.
為了縮短模塊的啟動時間, 可以將當前不需要的某些工作推遲執(zhí)行
確保對象中的某些字段能優(yōu)先初始化
為了確保對象中的某些字段能優(yōu)先初始化, 我們需要對其他字段進行惰性化處理
需求
定義一個方法用來獲取兩個整數(shù)和, 通過"惰性"技術調用該方法, 然后打印結果.
參考代碼
//1. 定義方法, 用來獲取兩個整數(shù)和
def getSum(a:Int, b:Int) = {
println("getSum方法被執(zhí)行了...")
a + b
}
//2. 通過"惰性"方式調用該方法.
lazy val sum = getSum(1, 2) //此時我們發(fā)現(xiàn)getSum方法并沒有執(zhí)行, 說明它的執(zhí)行被推遲了.
//3. 打印結果, 并觀察
println("sum: " + sum) //打印結果為sum: 3, 說明首次使用方法返回值時, 方法才會加載執(zhí)行.
1.6 方法參數(shù)
scala中的方法參數(shù),使用比較靈活。它支持以下幾種類型的參數(shù):
默認參數(shù)帶名參數(shù)變長參數(shù)
1.6.1 默認參數(shù)
在定義方法時可以給參數(shù)定義一個默認值。
示例
定義一個計算兩個整數(shù)和的方法,這兩個值分別默認為10和20調用該方法,不傳任何參數(shù)
參考代碼
//1. 定義一個方法, 用來獲取兩個整數(shù)的和
// x,y的默認值分別為10和20
def getSum(x:Int = 10, y:Int = 20) = x + y
//2. 通過默認參數(shù)的形式, 調用方法
val sum = getSum()
//3. 打印結果
println("sum: " + sum)
1.6.2 帶名參數(shù)
在調用方法時,可以指定參數(shù)的名稱來進行調用。
示例
定義一個計算兩個整數(shù)和的方法,這兩個值分別默認為10和20調用該方法,只設置第一個參數(shù)的值
參考代碼
//1. 定義一個方法, 用來獲取兩個整數(shù)的和
def getSum(x:Int = 10, y:Int = 20) = x + y
//2. 通過默認參數(shù)的形式, 調用方法
val sum = getSum(x=1)
//3. 打印結果
println("sum: " + sum)
1.6.3 變長參數(shù)
如果方法的參數(shù)是不固定的,可以將該方法的參數(shù)定義成變長參數(shù)。
語法格式:
def 方法名(參數(shù)名:參數(shù)類型*):返回值類型 = {
//方法體
}
注意:
在參數(shù)類型后面加一個*號,表示參數(shù)可以是0個或者多個一個方法有且只能有一個變長參數(shù), 并且變長參數(shù)要放到參數(shù)列表的最后邊.
**示例一: **
定義一個計算若干個值相加的方法調用方法,傳入以下數(shù)據(jù):1,2,3,4,5
參考代碼
//1. 定義一個計算若干個值相加的方法
def getSum(a:Int*) = a.sum
//2. 調用方法,傳入一些整數(shù), 并獲取它們的和
val sum = getSum(1,2,3,4,5)
//3. 打印結果
println("sum: " + sum)
1.7 方法調用方式
在scala中,有以下幾種方法調用方式:
后綴調用法中綴調用法花括號調用法無括號調用法
注意: 在編寫spark、flink程序時,會經常使用到這些方法調用方式。
1.7.1 后綴調用法
這種方法與Java沒有區(qū)別, 非常簡單.
語法
對象名.方法名(參數(shù))
示例
使用后綴法調用Math.abs, 用來求絕對值
參考代碼
//后綴調用法
Math.abs(-1) //結果為1
1.7.2 中綴調用法
語法
對象名 方法名 參數(shù)
例如:1 to 10
注意: 如果有多個參數(shù),使用括號括起來
示例
使用中綴法調用Math.abs, 用來求絕對值
//中綴調用法
Math abs -1 //結果為1
擴展: 操作符即方法
來看一個表達式, 大家覺得這個表達式像不像方法調用?
1 + 1
在scala中,+ - * / %等這些操作符和Java一樣,但在scala中,
所有的操作符都是方法操作符是一個方法名字是符號的方法
1.7.3 花括號調用法
語法
Math.abs{
// 表達式1
// 表達式2
}
注意: 方法只有一個參數(shù),才能使用花括號調用法
示例
使用花括號調用法Math.abs求絕對值
參考代碼
//花括號調用法
Math.abs{-10} //結果為: 10
1.7.4 無括號調用法
如果方法沒有參數(shù),可以省略方法名后面的括號
示例
定義一個無參數(shù)的方法,打印"Hello, Scala!"使用無括號調用法調用該方法
參考代碼
//1. 定義一個無參數(shù)的方法,打印"Hello, Scala!"
def sayHello() = println("Hello, Scala!")
//2. 調用方法
sayHello
注意:
在Scala中, 如果方法的返回值類型是Unit類型, 這樣的方法稱之為過程(procedure)過程的等號(=)可以省略不寫. 例如:
def sayHello() = println("Hello, Scala!")
//可以改寫為
def sayHello() { println("Hello, Scala!") } //注意: 這個花括號{}不能省略
2. 函數(shù)
scala支持函數(shù)式編程,將來編寫Spark/Flink程序會大量使用到函數(shù), 目前, 我們先對函數(shù)做一個簡單入門, 在后續(xù)的學習過程中, 我們會逐步重點講解函數(shù)的用法.
2.1 定義函數(shù)
語法
val 函數(shù)變量名 = (參數(shù)名:參數(shù)類型, 參數(shù)名:參數(shù)類型....) => 函數(shù)體
注意:
在Scala中, 函數(shù)是一個對象(變量)類似于方法,函數(shù)也有參數(shù)列表和返回值函數(shù)定義不需要使用def定義無需指定返回值類型
2.2 示例
**需求: **
定義一個計算兩個整數(shù)和的函數(shù)調用該函數(shù)
參考代碼
//1. 定義一個用來計算兩個整數(shù)和的函數(shù), 并將其賦值給變量sum
val getSum = (x:Int, y:Int) => x + y
//2. 調用函數(shù).
val result = getSum(1,2)
//3. 打印結果
println("result: " + result)
2.3 方法和函數(shù)的區(qū)別
在Java中, 方法和函數(shù)之間沒有任何區(qū)別, 只是叫法不同. 但是在Scala中, 函數(shù)和方法就有區(qū)別了, 具體如下:
方法是隸屬于類或者對象的,在運行時,它是加載到JVM的方法區(qū)中可以將函數(shù)對象賦值給一個變量,在運行時,它是加載到JVM的堆內存中函數(shù)是一個對象,繼承自FunctionN,函數(shù)對象有apply,curried,toString,tupled這些方法。方法則沒有
結論: 在Scala中, 函數(shù)是對象, 而方法是屬于對象的, 所以可以理解為: 方法歸屬于函數(shù).
示例
演示方法無法賦值給變量
//1. 定義方法
def add(x:Int,y:Int)= x + y
//2. 嘗試將方法賦值給變量.
//val a = add(1, 2) //不要這樣寫, 這樣寫是在"調用方法", 而不是把方法賦值給變量
val a = add
//3. 上述代碼會報錯
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
2.4 方法轉換為函數(shù)
有時候需要將方法轉換為函數(shù). 例如: 作為變量傳遞,就需要將方法轉換為函數(shù)
格式
val 變量名 = 方法名 _ //格式為: 方法名 + 空格 + 下劃線
注意: 使用 _即可將方法轉換為函數(shù)
示例
定義一個方法用來計算兩個整數(shù)和將該方法轉換為一個函數(shù),并賦值給變量
參考代碼
//1. 定義一個方法用來計算兩個整數(shù)和
def add(x:Int, y:Int)= x + y
//2. 將該方法轉換為一個函數(shù),并賦值給變量
val a = add _
//3. 調用函數(shù), 用來獲取兩個整數(shù)的和.
val result = a(1, 2)
//4. 打印結果
println("result: " + result)
3. 案例: 打印nn乘法表
3.1 需求
定義方法實現(xiàn), 根據(jù)用戶錄入的整數(shù), 打印對應的乘法表。
例如: 用戶錄入5,則打印55乘法表,用戶錄入9,則打印99乘法表。
3.2 目的
考察鍵盤錄入和方法, 函數(shù)的綜合運用.體會方法和函數(shù)的不同.
3.3 步驟
定義方法(或者函數(shù)), 接收一個整型參數(shù).通過for循環(huán)嵌套實現(xiàn), 根據(jù)傳入的整數(shù), 打印對應的乘法表.調用方法(函數(shù)), 輸出結果.
3.4 參考代碼
方式一: 通過方法實現(xiàn)
//1. 定義一個方法, 接收一個整型參數(shù).
def printMT(n:Int) = { //Multiplication Table(乘法表)
//2. 通過for循環(huán)嵌套實現(xiàn), 根據(jù)傳入的整數(shù), 打印對應的乘法表.
for(i <- 1 to n; j <- 1 to i) {
print(s"${j} * ${i} = ${j * i}\t");
if(j==i) println()
}
}
//3. 調用方法
printMT(5)
//優(yōu)化版: 上述定義方法的代碼可以合并為一行(目前只要能看懂即可)
/*def printMT(n:Int) = for(i <- 1 to n; j <- 1 to i) print(s"${j} * ${i} = ${j * i}" + (if(j==i) "\r\n" else "\t"))*/
方式二: 通過函數(shù)實現(xiàn)
//1. 定義一個函數(shù), 接收一個整型參數(shù).
val printMT = (n:Int) => {
//2. 通過for循環(huán)嵌套實現(xiàn), 根據(jù)傳入的整數(shù), 打印對應的乘法表.
for(i <- 1 to n; j <- 1 to i) {
print(s"${j} * ${i} = ${j * i}\t");
if(j==i) println()
}
}
//3. 調用函數(shù)
printMT(9)
//優(yōu)化版: 上述定義函數(shù)的代碼可以合并為一行(目前只要能看懂即可)
/*val printMT = (n:Int) => for(i <- 1 to n; j <- 1 to i) print(s"${j} * ${i} = ${j * i}" + (if(j==i) "\r\n" else "\t"))*/
scala學習配套視頻
柚子快報邀請碼778899分享:后端 Scala第五章節(jié)
好文鏈接
本文內容根據(jù)網絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉載請注明,如有侵權,聯(lián)系刪除。