您好,登錄后才能下訂單哦!
好程序員大數(shù)據(jù)學(xué)習(xí)路線分享高階函數(shù),我們通常將可以做為參數(shù)傳遞到方法中的表達(dá)式叫做函數(shù)
高階函數(shù)包含:作為值的函數(shù)、匿名函數(shù)、閉包、柯里化等等。
定義函數(shù)時格式:val 變量名 =?(輸入?yún)?shù)類型和個數(shù))?=>?函數(shù)實(shí)現(xiàn)和返回值類型和個數(shù)
“=”表示將函數(shù)賦給一個變量
“=>”左面表示輸入?yún)?shù)名稱、類型和個數(shù),右邊表示函數(shù)的實(shí)現(xiàn)和返回值類型和參數(shù)個數(shù)
作為值的函數(shù)
定義函數(shù)
scala> val func = (x:Int) => x * x
func: Int => Int = <function1>
scala> val func:Int => Int = x => x * x
func: Int => Int = <function1>
scala> func(3)
res0: Int = 9
函數(shù)調(diào)用
scala> val arr = Array(1,2,3,4)
arr: Array[Int] = Array(1, 2, 3, 4)
scala> val res = arr.map(x => func(x))
res: Array[Int] = Array(1, 4, 9, 16)
scala> val res = arr.map(func(_))
res: Array[Int] = Array(1, 4, 9, 16)
scala> val res = arr.map(func)
res: Array[Int] = Array(1, 4, 9, 16)
將方法轉(zhuǎn)化為函數(shù)
scala> def m1(x:Int):Int = x * x
m1: (x: Int)Int
scala> def m1(x:Int) = x * x
m1: (x: Int)Int
scala> def m2(x:Int) {x * x}
m2: (x: Int)Unit
scala> val f1 = m1 _
f1: Int => Int = <function1>
scala> val res = arr.map(x => m1(x))
res: Array[Int] = Array(1, 4, 9, 16)
scala> val res = arr.map(m1(_))
res: Array[Int] = Array(1, 4, 9, 16)
scala> val res = arr.map(m1)
res: Array[Int] = Array(1, 4, 9, 16)
匿名函數(shù)
在Scala中,你不需要給每一個函數(shù)命名,沒有將函數(shù)賦給變量的函數(shù)叫做匿名函數(shù)
scala> arr.map((x:Int) => x * x)
res3: Array[Int] = Array(1, 4, 9, 16)
scala> arr.map(x => x * x)
res4: Array[Int] = Array(1, 4, 9, 16)
scala> arr.map(m1)
res1: Array[Int] = Array(1, 4, 9, 16)
scala> arr.map(_ * 2)
res2: Array[Int] = Array(2, 4, 6, 8)
閉包
閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)
可以理解成,定義在一個函數(shù)內(nèi)部的函數(shù)
本質(zhì)上,閉包是將函數(shù)內(nèi)部和函數(shù)外部鏈接起來的橋梁
object Bibao {
??def sum(f:Int => Int):(Int,Int) => Int = {
????def sumf(a:Int,b:Int):Int = {
??????if (a > b) 0 else f(a)+sumf(a + 1,b)
????}
????sumf ?//隱式轉(zhuǎn)換成函數(shù)
??}
??def main(args: Array[String]): Unit = {
????def sumInts = sum(x => x)
????println(sumInts(1,2))
??}
}
柯里化
柯里化指的是將原來接收兩個參數(shù)列表的方法或函數(shù)變成新的一個參數(shù)列表的方法或函數(shù)的過程
聲明和轉(zhuǎn)化
scala> def curry(x:Int)(y:Int) = x * y ?//聲明
curry: (x: Int)(y: Int)Int
scala> curry(3)(4)
res8: Int = 12
scala> val curry1 = curry(3) ?//轉(zhuǎn)換成方法 : 加""
curry1: Int => Int = <function1>
scala> curry1(5)
res9: Int = 15
scala> def curry2(x:Int) = (y:Int) => x * y ?//聲明
curry2: (x: Int)Int => Int
scala> val func = curry2(2) ?//直接轉(zhuǎn)化
func: Int => Int = <function1>
scala> func(4)
res16: Int = 8
scala> def curry3() = (x:Int) => x * x
curry3: ()Int => Int
scala> val func = curry3() ???//轉(zhuǎn)化空參
func: Int => Int = <function1>
scala> func(3)
res17: Int = 9
柯里化需要與隱式轉(zhuǎn)換相結(jié)合
implicit ?隱式的 -> 隱式值在當(dāng)前會話中同類型只能定義一次,不同類型可定義多個
scala> def m1(x:Int)(implicit y:Int=5) = x * y
m1: (x: Int)(implicit y: Int)Int
scala> m1(3)
res10: Int = 15
scala> m1(3)(6) ???//隱式值可以改變
res11: Int = 18
scala> implicit val x = 100 ?//定義成全局的隱式值,可以覆蓋
x: Int = 100
scala> m1(3)(6)
res12: Int = 18
scala> m1(3)
res13: Int = 300
scala> implicit val y = "abc"
y: String = abc
案例: 把數(shù)組中元祖的value相加
scala> val arr = Array(("xixi",1),("haha",2),("heihei",3))
arr: Array[(String, Int)] = Array((xixi,1), (haha,2), (heihei,3))
scala> ?arr.foldLeft(0)( + ._2) ?//(初始值)(上次計算結(jié)果+循環(huán)出的結(jié)果)
res15: Int = 6
Curry的Demo
object Context{ ??//一般情況會新建類,再在此地調(diào)用
??implicit val a = "yaoyao"
??implicit val b = 100
}
object Curry {
??//與變量沒有關(guān)系,系統(tǒng)自己匹配相同類型的值
??implicit val a = "yaoyao"
??implicit val b = 100
??def m1(str:String)(implicit name:String="xiaodan"){
????println(str + name)
??}
??def main(args: Array[String]): Unit = {
????import Context.a
????m1("Hello ")
??}
}
隱式轉(zhuǎn)換
作用: 隱式的對類的方法進(jìn)行增強(qiáng),豐富現(xiàn)有類庫的功能
隱式轉(zhuǎn)換:
繼承 -> 通過方法的重寫來對父類的方法增強(qiáng)
代理模式 -> 遠(yuǎn)程代理,多用于網(wǎng)站,代理一個實(shí)例,可以對實(shí)例方法增強(qiáng),在調(diào)用方法之前
????????代理,方法之后環(huán)繞
????裝飾模式 -> 裝飾模式也叫包裝模式,用java讀取文件時要用到IO流,也是對實(shí)例方法增強(qiáng) ?????????????????????????
????new BufferInputStream(new FileInputStream).read()
就是用到了裝飾模式和門面模式 ->
裝飾模式是顯示的包裝,隱式轉(zhuǎn)換就是隱式的做了包裝
門面模式起到了隱式包裝的作用
隱式轉(zhuǎn)換函數(shù) : 是指以implicit關(guān)鍵字聲明的帶有單個參數(shù)的函數(shù)
案例: 用隱式轉(zhuǎn)換,實(shí)現(xiàn)從給定的URI直接能調(diào)用read方法讀取文件內(nèi)容
object MyPredef {
??//implicit def fileToRichFile(file:String) = new RichFile(file)
??implicit val fileToRichFile = (file:String) =>new RichFile(file)
}
object RichFile {
??def main(args: Array[String]): Unit = {
????val file = "e://wordcount.txt"
// ???//顯示的實(shí)現(xiàn)了對file的方法增強(qiáng)
// ???val richFile = new RichFile(file)
// ???val content: String = richFile.read()
// ???println(content)
????//隱式轉(zhuǎn)換
????import MyPredef.fileToRichFile
????val content = file.read()
????println(content)
??}
}
class RichFile(val file:String){
??//創(chuàng)建read方法
??def read():String = {
????Source.fromFile(file).mkString
??}
}
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。