大數(shù)據(jù)學(xué)習(xí)路線分享高階函數(shù),我們通常將可以做為參數(shù)傳遞到方法中的表達(dá)式叫做函數(shù) 高階函數(shù)包含:作為值的函數(shù)、匿名函數(shù)、閉包、柯里化等等。 定義函數(shù)時(shí)格式:val 變量名 = (輸入?yún)?shù)類型和個(gè)數(shù)) => 函數(shù)實(shí)現(xiàn)和返回值類型和個(gè)數(shù) “=”表示將函數(shù)賦給一個(gè)變量 “=>”左面表示輸入?yún)?shù)名稱、類型和個(gè)數(shù),右邊表示函數(shù)的實(shí)現(xiàn)和返回值類型和參數(shù)個(gè)數(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中,你不需要給每一個(gè)函數(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ù) 可以理解成,定義在一個(gè)函數(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)) } } |
柯里化 柯里化指的是將原來接收兩個(gè)參數(shù)列表的方法或函數(shù)變成新的一個(gè)參數(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)前會(huì)話中同類型只能定義一次,不同類型可定義多個(gè) 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) //(初始值)(上次計(jì)算結(jié)果+循環(huán)出的結(jié)果) res15: Int = 6 |
Curry的Demo object Context{ //一般情況會(huì)新建類,再在此地調(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)換 作用: 隱式的對(duì)類的方法進(jìn)行增強(qiáng),豐富現(xiàn)有類庫的功能 隱式轉(zhuǎn)換: 繼承 -> 通過方法的重寫來對(duì)父類的方法增強(qiáng) 代理模式 -> 遠(yuǎn)程代理,多用于網(wǎng)站,代理一個(gè)實(shí)例,可以對(duì)實(shí)例方法增強(qiáng),在調(diào)用方法之前 代理,方法之后環(huán)繞 裝飾模式 -> 裝飾模式也叫包裝模式,用java讀取文件時(shí)要用到IO流,也是對(duì)實(shí)例方法增強(qiáng) new BufferInputStream(new FileInputStream).read() 就是用到了裝飾模式和門面模式 -> 裝飾模式是顯示的包裝,隱式轉(zhuǎn)換就是隱式的做了包裝 門面模式起到了隱式包裝的作用 隱式轉(zhuǎn)換函數(shù) : 是指以implicit關(guān)鍵字聲明的帶有單個(gè)參數(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)了對(duì)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 } }
|