Kotlin的高阶函数和常用高阶函数
Kotlin的高階函數(shù)和常用高階函數(shù)
高階函數(shù)的定義
將函數(shù)當(dāng)做參數(shù)或者是返回值的函數(shù)
什么是高階函數(shù)
可以看看我們常用的 函數(shù):
首先我們可以知道, 是 的擴(kuò)展函數(shù),然后參數(shù)是 ,但是 不再像和我們以前Java那樣傳遞的是一個對象,這時傳遞的是一個函數(shù)。這個函數(shù)的入?yún)?,返回值為 。所以 也是一個高階函數(shù),因?yàn)樗鼘⒑瘮?shù)當(dāng)做參數(shù)進(jìn)行傳遞了。我們嘗試著去調(diào)用一下 函數(shù):
調(diào)用的時候,我們將 函數(shù)傳遞給了 函數(shù),這里采用的是函數(shù)引用。就上訴代碼,我們還可以結(jié)合 表達(dá)式來進(jìn)行處理:
其實(shí)以上幾種的方式得到的結(jié)果都是一樣的,但是第一種就是簡潔了許多。
我們再定義一個類,用來打印 的值:
根據(jù)函數(shù)引用的特性,我們可以這樣調(diào)用 函數(shù):。由于 中的 函數(shù)的入?yún)㈩愋褪?類型,也就是任意類型,不管 傳遞的是什么值都可以接收。那現(xiàn)在我們再將其作為 的參數(shù)傳遞進(jìn)去:
編譯器告訴我們這個是錯誤的。那我們來分析一下吧:我們再定義一個 類
然后進(jìn)行以下操作:
可以看到 分別對 和 的解釋:
是一個方法,然后參數(shù)類型為 ,返回值為
也是一個方法,但是參數(shù)有兩個,分別是 和 類型, 返回值為
在 中,只有一個參數(shù)傳遞,但是 需要的是兩個參數(shù),肯定就會報錯,所以我們需要對此進(jìn)行修改:
這個樣子就OK了。
常用高階函數(shù)
map:變換
通常我們會使用以下的方式來實(shí)現(xiàn)對集合中的元素進(jìn)行修改的操作:
如果采用這種方式,遠(yuǎn)遠(yuǎn)不能體現(xiàn)Kotlin的優(yōu)勢了,這個和Java有什么區(qū)別呢?「狗子,上map」:
從打印結(jié)果可以看到他們的實(shí)現(xiàn)效果是一模一樣的,這個就是 的功能,可以對集合中的元素進(jìn)行你想要的操作,是不是跟 的 很類似呢!我們來細(xì)看一下 的實(shí)現(xiàn)原理:
方法中主要做的就是調(diào)用 方法,然后傳遞的是新創(chuàng)建并且初始長度為10的 和 函數(shù),在 方法中,對集合進(jìn)行迭代,然后將進(jìn)行變換后的數(shù)據(jù)添加到新的集合中,最后返回新的集合。
操作不僅可以將元素變換成與之前類型相同的元素,也可以變化成與之前元素類型不同的元素,具體你想變換成什么類型,這個是不做限制的。
flatMap:變換
看起來跟 很相似,其實(shí)真的很類似,搞得有時候自己都不知道應(yīng)該使用哪個操作符了,那就從源碼來看看它們之間的區(qū)別吧。
可以看到 中的參數(shù) 是一個返回值為 的函數(shù),而 的參數(shù) 是一個返回值為 的函數(shù)。然后調(diào)用 方法,將 和一個新創(chuàng)建的 傳遞給了 方法。在 方法中,對當(dāng)前的集合進(jìn)行了迭代,然后將執(zhí)行過變換操作后的集合數(shù)據(jù)全部添加到新的集合中,最終返回新的集合。
和 的主要區(qū)別就是在于傳入的函數(shù)的返回值,一個是任意對象,一個是實(shí)現(xiàn)了 接口的對象
reduce
例子:打印集合中的元素之和
還是直接對源碼進(jìn)行分析吧,感覺看了源碼就一目了然了。
首先對當(dāng)前的集合進(jìn)行判空處理,接著將第一個元素賦值給 , 的類型是 。然后對當(dāng)前集合進(jìn)行迭代處理,并調(diào)用我們傳遞進(jìn)去的參數(shù) , 函數(shù)中傳遞了兩個參數(shù),一個是 類型的,一個是集合元素類型的。 函數(shù)的返回值也是 類型的,將 的返回值重新賦值給 。迭代完畢以后返回我們的 。
其實(shí)通過我們解讀源碼以后,我們就可以知道 函數(shù)會將上一次的計(jì)算結(jié)果傳遞到下一次計(jì)算中,我們可以利用這個方式來實(shí)現(xiàn)以下字符串拼接,當(dāng)然我們的字符串拼接有其他更好的方式,這里只是做為講解 的例子而已:
fold:能夠添加初始值的reduce
不得不說, 跟 的作用基本是一致的,只是 能夠添加初始值,什么叫做能夠添加初始值呢?讓我們來舉個栗子看看唄!
還是看源碼吧:
看著源碼就會覺得這些函數(shù)的操作很是簡單了。 函數(shù)還有很多的兄弟:
說的再多也不如看結(jié)果
這個函數(shù)就是多了一個 的參數(shù),具體的用處暫時沒有發(fā)現(xiàn),就不做數(shù)據(jù)打印了。
filter:過濾
例子:過濾集合中的奇數(shù)
上源碼:
在 中創(chuàng)建新的集合 ,將 和 函數(shù)一并傳遞給 函數(shù)。在 函數(shù)中,先對當(dāng)前的集合進(jìn)行遍歷,如果滿足條件 就將當(dāng)前的元素添加到新的集合中, 就是我們傳遞進(jìn)來的那個函數(shù),返回值是一個 類型的。
takeWhile:截取集合中的數(shù)據(jù),直到第一個不滿足條件的元素為止
例子:截取集合中不能夠被5整除的數(shù),直到第一個不滿足條件的元素為止。
源碼:
let:將調(diào)用者當(dāng)做參數(shù)傳遞給指定的函數(shù)
例子:省略if空判斷
源碼:
源碼也是很簡單,就是將調(diào)用者傳遞給傳入進(jìn)來的函數(shù)并執(zhí)行傳入進(jìn)來的函數(shù)。
apply:執(zhí)行指定函數(shù),并且返回調(diào)用者
例子:修改person類的age屬性
上訴的例子真的只是例子,它沒有跟你講 有多強(qiáng)大,它只是描述了的作用。源碼:
就是單純的執(zhí)行函數(shù) 并返回調(diào)用者。
with
例子:文件讀取
源碼:
接收兩個參數(shù),一個是 ,上訴例子中就是 ,另一個就是 ,在上訴例子中,我們使用了 表達(dá)式,所以這個函數(shù)就移到了括號外面了。
疑惑點(diǎn)
函數(shù)定義中 `T.() -> Unit` 和 `() -> Unit` 的區(qū)別
我們一般定義函數(shù)都會選擇定義
上訴代碼表示: 的擴(kuò)展方法 接收一個 的函數(shù),該函數(shù)是無參無返回的。
那我們再見識見識 這種方式定義的方法,其實(shí)也很多見了:
可以看到 函數(shù)使用的是 這種方式,他們兩到底有啥區(qū)別呢?
我在 定義了兩個方法:
分別使用 調(diào)用這兩個方法試試:
從圖片中可以看出 : 中的 對象指的是調(diào)用對象 ,也就是 ,而 沒有提示,那么我們就看打印吧:
原來 方法中的 對象指的是外部對象,在這里就是我們的 對象。
總結(jié)
這兩個函數(shù)唯一的區(qū)別就是 與 的區(qū)別,我們調(diào)用時,在代碼塊里面寫this,的時候,根據(jù)代碼提示,我們可以看到,連個this代表的含義不一樣, 里的this代表的是自身實(shí)例,而 里,this代表的是外部類的實(shí)例
感謝
[Kotlin中,函數(shù)作為參數(shù),T.()->Unit 和 ()->Unit 的區(qū)別][https://www.jianshu.com/p/88a656e59c61]
This is All
轉(zhuǎn)載于:https://www.cnblogs.com/vana/p/10837702.html
總結(jié)
以上是生活随笔為你收集整理的Kotlin的高阶函数和常用高阶函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 辗转相除最小公倍数的递归求法
- 下一篇: spring+cxf