一文弄懂 kotlin lambda與高階函數

閱讀本文能解決什麼問題

我發現不少學過kotlin的人,遲遲不敢在項目中運用,主要是由於kotlin的 lambda與高階函數沒有學好。這2個東西每每是一塊兒運用的。 網上不少相似的文章都講的不夠通透,致使大部分人都卡在這裏。或者有一些人即便寫了kotlin 可是也沒用好lambda與高階函數,致使kotlin的代碼 全是java的味道。java

你們能夠用一下新版本的android studio,而後新建一個kotlin語言的loginActivity,若是裏面的代碼你能無障礙的基本看懂,那這篇文章就不用再看了,若是看起來障礙很大,那麼建議你仔細看完這篇文章,以後再返回去看這個loginActivity的代碼,相信結果是徹底不同的。android

最後總結一下個人觀點:想寫好Kotlin的代碼就看你對lambda與高階函數理解的有多深,早期糾結那些晦澀的語法糖沒有任何意義api

到底啥是匿名函數

那這個func 又怎麼理解呢?他爲啥能夠接受一個函數做爲參數?數組

這裏有人會問了,你咋知道 這個匿名函數是沒有返回值的啊?bash

由於lambda表達式有一個特色,lambda括號裏面的函數最後一行就是這個函數的返回值, 圖中咱們最後一行 是個print語句,這個print函數顯然是沒有返回值的,因此這個lambda 也就是這個匿名函數也就沒有了返回值了。app

帶參數的lambda

而後咱們反編譯看一下這段代碼函數

咱們換個寫法ui

咱們再看一下反編譯的:spa

下面咱們再改進一下寫法:3d

那固然還有終極的簡寫,也就是日常咱們使用最多的寫法:

不少人學很差lambda就是由於上來就看這個最簡單的寫法,而不知道這種寫法是怎麼來的。你搞清楚 這種寫法的進化緣由,天然就真正理解了lambda了。

來個更進一步 2個參數的

看下執行結果

實際上kotlin中的lambda 就是一個匿名函數,java8的lambda表達式 倒是一個sam的語法糖

高階函數

有了前面lambda 的鋪墊,高階函數 的理解就不難了。 下面給高階函數下一個定義: 參數類型包含函數類型,或者返回值類型是一個函數類型 的函數 均可以稱之爲是高階函數。

來看幾個簡單的高階函數的例子:

看下源碼:

再看個函數

而後咱們看一下map函數的定義

因此你看高階函數 也沒什麼難的,主要你能理解lambda 那麼你就能理解好高階函數

谷歌源碼裏最經常使用的幾個高階函數

無非就是let run also apply use 這麼5個,網上關於這幾個函數的資料不少,可是介紹的我以爲都至關通常,這裏我從新介紹一下 這幾個函數對應的使用場景。 掌握了他們,能夠說 理解kotlin的代碼 就不會存在什麼障礙了。

這裏要着重說明的是,其實run函數和apply函數 並沒啥大做用。平時本身寫 主要仍是let also 和use

看一段代碼,看看let和also的區別

最後一個use操做符,是我的最愛的一個操做符,由於這東西真的省事。我演示一遍你就知道他有多省事了!

最後用一張圖來總結:

高階函數-集合的變換

咱們平時開發業務代碼時 其實最主要的工做就是對一個集合進行增刪改查,過濾啊 之類的操做。 kotlin中 提供了大量對集合操做的 高階函數,理解好他們 對你讀代碼或者是寫代碼的操做都是很是很是有幫助的。

前面的代碼中咱們已經演示過了for each循環的用法 這裏補充一點,foreach函數是能夠提早跳出的。

固然上面的寫法通常是不推薦的,由於確實很迷惑人。 有更高級的函數 能夠知足你對集合的要求。

看下圖:

看個例子:

有時候咱們對一個集合的操做,可能不止一個函數,須要多個函數協同操做,這個時候有更方便的 寫法。

有人要問了,這個asSeq不調用 是啥效果?咱們能夠看一下

再看一個例子

看下flatmap

集合的聚合操做

先看一張圖 瞭解一下主要的聚合操做

看下fold的使用

其他的2個高階函數就再也不演示了。你們用到的時候自行查閱api便可。

試試高階函數和lambda 怎麼組合使用 解決問題?

前面已經學完了lambda和大部分高階函數,這裏咱們組合一下他們的用法,從新將知識串起來。

1.統計一個文件裏 除了空格字符之外,每一個字符出現的次數(儘可能只使用lambda)

/**
 *  1.讀文件 而後把文件的內容 轉成char的數組
 *  2.過濾數組,空格符直接忽略
 *  3.用groupBy 來將整個數組 從新分組(分組的結果是一個map), key就是出現的字符,value就是出現的所有字符
 *  4.用map操做符 再將這個map 拍平成一個list,這個list的 內容形如:e 出現次數: 21
 *  5.用let操做符 將結果打印出來便可
 */
fun main() {

    File("/Users/wuyue/IdeaProjects/KotlinTest/src/enumTest.kt").readText().toCharArray().filterNot {
        it.isWhitespace()
    }.groupBy {
        it
    }.map {
        it.key + " 出現次數: " + it.value.size
    }.let {
        println(it)
    }
}

複製代碼
相關文章
相關標籤/搜索