1 簡介
Scala函數式編程是scala的重中之重,老師多次強調它的重要性,spark當中的計算都是用scala函數式編程來做,高級函數也是其獨特的一個特性,並且spark基於集合,這樣可以使scala發揮其對於集合計算的強大功能。首先,函數/變量同是一等公民,函數與變量同等地位,函數的定義可以單獨定義,可以不依賴於類、接口或者object,而且獨立存在,獨立使用,並且可以賦值給變量。
函數可以以一種特殊對象的形式存在 ,那麼函數就可以作爲方法的參數和方法的返回值使用!!
- 函數的參數是函數的函數或者方法
- 函數的返回值是函數的函數或者方法
- 函數的參數和返回值都是函數的函數或者方法
使用高階函數的一個原因是減少冗餘的代碼,使scala編程變得更加靈活簡潔!在不使用高階函數的時候 ,我們會爲每個具體的功能寫一個方法,或者函數如下
object SalaryRaiser {
def smallPromotion(salaries: List[Double]): List[Double] =
salaries.map(salary => salary * 1.1)
def greatPromotion(salaries: List[Double]): List[Double] =
salaries.map(salary => salary * math.log(salary))
def hugePromotion(salaries: List[Double]): List[Double] =
salaries.map(salary => salary * salary)
}
顯然上面的所有的函數處理的都是每個人的工資這種操作,如果有了高階函數以後我們的書寫是這樣的
object SalaryRaiser {
def smallPromotion(salaries: List[Double],f:(Double)=>Double): List[Double] = salaries.map(f)
}
2 函數或者方法的參數是函數
object HighFunction {
/**
* 高階函數
*
* @param x
* @param y
* @param f
* @return
*/
def highFunc(x: Int, y: Int, f: (Int, Int) => Int): Int = {
f(x, y)
}
def main(args: Array[String]): Unit = {
/**
* 參數一
* 參數二
* 參數三 函數 函數的邏輯同處理數據不一樣
* (x,y)=>x+y 求和
* (x,y)=>x*y
* (x,y)=>x-y
* (x,y)=>if(x>y) x else y 求大值
*/
println(highFunc(20, 3, (x, y) => {
if (x > y) x else y
}))
}
}
上面的例子中方法的第三個參數是一個函數 , 處理兩個Int類型的數據返回一個Int類型的數據
def highFunc(x: Int, y: Int, f: (Int, Int) => Int): Int = {
f(x, y)
}
當我們在調用這個方法的時候,傳入的第三個參數是函數(也可以是方法,底層做了方法到函數的轉換) , 那麼傳入的函數是要是處理兩個Int返回一個Int類型的函數即可, 可以是事先定義好的函數 ,也可以是匿名函數!!
// 傳入的參數是匿名函數 求兩個數據的乘積 highFunc(3,2,(x:Int,y:Int)=>x*y) highFunc(3,2,(x,y)=>x*y) // Int可以省略// 傳入一個事先定義好的函數
def operater1(x: Int, y: Int): Int = { x + y }
highFunc(3,2,operater1)
我們學習的很多集合的函數的參數都是函數 比如 map , filter,flatMap...
3 函數或者方法的返回值是函數
// 定義一個方法 返回值是函數
def op(str:String)={
// 返回值是一個函數
(x:String) => x+str.toUpperCase
}
def op2(b:Boolean) = {
(x:String)=>
if(b) {
x.toUpperCase
}else{
x
}
}
val str: String = demo.op("abc")("enene~~~")
println(str)
println(demo.op2(false)("hello"))