您好,登錄后才能下訂單哦!
[TOC]
測試代碼如下:
package cn.xpleaf.bigdata.p4.function
/**
* scala中關(guān)于函數(shù)的操作
*/
object _01FunctionOps {
def main(args: Array[String]): Unit = {
functionOps1
}
/**
* 作為值傳遞的函數(shù)
* 將一個(gè)函數(shù)作為值傳遞給另外一個(gè)函數(shù)變量的時(shí)候,約定需要在函數(shù)后面加上:空格和下劃線
* 相當(dāng)于數(shù)據(jù)庫中的別名,或者數(shù)據(jù)庫表對(duì)應(yīng)的視圖
*/
def functionOps1: Unit = {
def sayHi(name:String) = println("Hello, " + name)
def sayHello = sayHi _
sayHello("xpleaf")
}
}
輸出結(jié)果如下:
Hello, xpleaf
測試代碼如下:
package cn.xpleaf.bigdata.p4.function
/**
* scala中關(guān)于函數(shù)的操作
*/
object _01FunctionOps {
def main(args: Array[String]): Unit = {
functionOps2
}
/**
* 匿名函數(shù),說白了就是沒有函數(shù)名字
* 匿名函數(shù)就和java中的匿名內(nèi)部類一樣,是只適合使用一次的函數(shù)
* 一般如果一個(gè)函數(shù)的參數(shù)是一個(gè)函數(shù),這種情況下多用匿名函數(shù)來作為參數(shù)進(jìn)行傳遞
*/
def functionOps2: Unit = {
val printName = (name:String) => println("你好," + name)
printName("xpleaf")
}
}
輸出結(jié)果如下:
你好,xpleaf
其實(shí)前面在學(xué)習(xí)ArrayBuffer的時(shí)候已經(jīng)有使用過匿名函數(shù):
scala> val ab = ArrayBuffer[Int](3, 8, 2, 20, 5, 7)
ab: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(3, 8, 2, 20, 5, 7)
scala> ab.sortWith((v1, v2) => v1 > v2)
res209: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(20, 8, 7, 5, 3, 2)
說明的作用有兩個(gè)(匿名函數(shù)作為參數(shù)和返回值為匿名函數(shù)),具體參考下面的測試代碼:
package cn.xpleaf.bigdata.p4.function
/**
* scala中關(guān)于函數(shù)的操作
*/
object _01FunctionOps {
def main(args: Array[String]): Unit = {
// functionOps1
// functionOps2
functionOps3
}
/**
* scala的高階函數(shù),就是函數(shù)的 [參數(shù)是函數(shù)] 的函數(shù),把這種函數(shù)稱為高階函數(shù)
*/
def functionOps3: Unit = {
// 1.匿名函數(shù)作為參數(shù)
def highOrderFunc(name:String, func:(String) => Unit): Unit = {
func(name)
}
highOrderFunc("xpleaf", (name:String) => println("Hello, " + name))
// 2.將匿名函數(shù)作為返回值傳遞給另外一個(gè)函數(shù)
def getGoodBayFunction(gMsg: String) = (gName: String) => println(gMsg + ", " + gName)
val goodbayFunction = getGoodBayFunction("good bye")
goodbayFunction("xpleaf")
}
}
輸出結(jié)果如下:
Hello, xpleaf
good bye, xpleaf
測試代碼如下:
package cn.xpleaf.bigdata.p4.function
import scala.collection.mutable.ArrayBuffer
/**
* scala中關(guān)于函數(shù)的操作
*/
object _01FunctionOps {
def main(args: Array[String]): Unit = {
// functionOps1
// functionOps2
// functionOps3
functionOps4
}
/**
* 對(duì)于匿名函數(shù)的省略寫法
*/
def functionOps4: Unit = {
val ab = ArrayBuffer[Int](1, 2, 3, 4, 5)
// val newAB = ab.map((x:Int) => x * 100)
// val newAB = ab.map((x) => x * 100)
// val newAB = ab.map(x => x * 100)
val newAB = ab.map(100 * _)
println(newAB) // ArrayBuffer(100, 200, 300, 400, 500)
}
}
輸出結(jié)果如下:
ArrayBuffer(100, 200, 300, 400, 500)
遍歷集合中的每一個(gè)元素,返回也是一個(gè)集合,集合大小和之前集合相等。
scala> (1 to 9).map(0.1 * _).foreach(println(_))
0.1
0.2
0.30000000000000004
0.4
0.5
0.6000000000000001
0.7000000000000001
0.8
0.9
scala> (1 to 9).map("*" * _).foreach(println(_))
*
**
***
****
*****
******
*******
********
*********
在這里,我們還用到了foreach,它和map很像,只不過它的函數(shù)并不返回任何值,foreach只是簡單的將函數(shù)應(yīng)用到每個(gè)元素而已。
按照過濾條件,將原集合中不符合條件的數(shù)據(jù)過濾掉
scala> (1 to 9).filter(line => line % 2 == 0).foreach(println(_))
2
4
6
8
scala> (1 to 9).filter(_ % 2 ==0).foreach(println)
2
4
6
8
scala> (1 to 9).reduce((v1:Int, v2:Int) => v1 + v2)
res4: Int = 45
scala> (1 to 9).reduce(_ + _)
res6: Int = 45
scala> (1 to 9).reduceLeft(_ + _)
res7: Int = 45
scala> (1 to 9).reduceRight(_ + _)
res8: Int = 45
可以寫下面一個(gè)函數(shù)來驗(yàn)證reduce函數(shù)的執(zhí)行過程:
scala> val process = (v1:Int, v2:Int) => println(s"v1=${v1}, v2=${v2}")
process: (Int, Int) => Unit = <function2>
scala> def pro(v1:Int, v2:Int):Int = {
| println(s"v1=${v1}, v2=${v2}")
| v1 + v2
| }
pro: (v1: Int, v2: Int)Int
scala> (1 to 9).reduce((v1:Int, v2:Int) => pro(v1, v2))
v1=1, v2=2
v1=3, v2=3
v1=6, v2=4
v1=10, v2=5
v1=15, v2=6
v1=21, v2=7
v1=28, v2=8
v1=36, v2=9
res0: Int = 45
scala> (1 to 9).reduceLeft((v1:Int, v2:Int) => pro(v1, v2))
v1=1, v2=2
v1=3, v2=3
v1=6, v2=4
v1=10, v2=5
v1=15, v2=6
v1=21, v2=7
v1=28, v2=8
v1=36, v2=9
res2: Int = 45
scala> (1 to 9).reduceRight((v1:Int, v2:Int) => pro(v1, v2))
v1=8, v2=9
v1=7, v2=17
v1=6, v2=24
v1=5, v2=30
v1=4, v2=35
v1=3, v2=39
v1=2, v2=42
v1=1, v2=44
res3: Int = 45
這樣的話執(zhí)行過程就非常清晰了,reduce和reduceLeft都是從左邊的操作數(shù)開始,而reduceRight是從右邊的操作數(shù)開始。
scala> (1 to 9).sortWith((v1:Int, v2:Int) => v1 > v2).foreach(println(_))
9
8
7
6
5
4
3
2
1
scala> (1 to 9).sortWith(_ > _).foreach(println)
9
8
7
6
5
4
3
2
1
函數(shù)的變量不在其作用域內(nèi)被調(diào)用,就是閉包的概念,看下面一個(gè)例子:
def closePackage: Unit ={
def mulBy(factor:Double) = (x:Double) => factor * x
val triple = mulBy(3)
val half = mulBy(0.5)
println(triple(14) +" " + half(14)) //42, 7
}
1)mulBy的首次調(diào)用將參數(shù)變量factor設(shè)為3,。該變量在(x:Double)=>factor *x
函數(shù)的函數(shù)體內(nèi)被引用。該函數(shù)被存入triple.然后參數(shù)變量factor從運(yùn)行時(shí)的棧上被彈出。
2)mulBy再次被調(diào)用,這次factor被設(shè)為0.5.該變量在(x:Double)=>factor *x
函數(shù)的函數(shù)體內(nèi)被引用,該函數(shù)被存入half.
每一個(gè)函數(shù)被稱為閉包(closure)。閉包有代碼和代碼用到的任何非局部變量定義構(gòu)成。
其實(shí)上面的mulBy
函數(shù)就類似于下面這個(gè):
def mulBy1(factor:Double, x:Double) = {
factor * x
}
原本還希望進(jìn)一步寫成下面這樣子的:
def mulBy2(factor:Double, x:Double) = {
def work(x:Double) = {
factor * x
}
return work
}
但在scala中不支持這樣的寫法,下面這樣寫才可以:
def mulBy2(factor:Double) = {
(x:Double) => factor * x
}
// 加個(gè)return也不行
之前在Python中使用過閉包,類似上面的例子,Python就可以這樣寫:
def mulBy(factor):
def work(x):
return factor * x
return work
測試如下:
>>> def mulBy(factor):
... def work(x):
... return factor * x
... return work
...
>>> triple = mulBy(3)
>>> half = mulBy(0.5)
>>> triple(14)
42
>>> half(14)
7.0
當(dāng)然,只是Python的語法格式就沒有scala那么靈活了。
1、柯里化(currying)指的是將原來接受2個(gè)參數(shù)的函數(shù)變成新的接受一個(gè)參數(shù)的函數(shù)的過程。新的函數(shù)返回一個(gè)以原有第二個(gè)參數(shù)作為參數(shù)的函數(shù)。
2、在函數(shù)調(diào)用的過程中,就變?yōu)榱藘蓚€(gè)函數(shù)連續(xù)調(diào)用的形式。在Spark源碼中,也有體現(xiàn),所以對(duì)()()這種形式的Curring函數(shù),一定要掌握。
以下函數(shù)接受一個(gè)參數(shù),生成另一個(gè)接受單個(gè)參數(shù)的函數(shù),要計(jì)算兩個(gè)數(shù)的乘積,調(diào)用如下:
/**
* curryingFunction: 柯里化函數(shù)
*/
def curryingFunction ={
def totalSum(x:Int, y:Int) = println( x + y)
//totalSum(4,5)
def totalSumAtTime(x:Int) = (y:Int) => x + y
println(totalSumAtTime(4)(5))
}
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。