閱讀本文能解決什麼問題
我發現很多學過kotlin的人,遲遲不敢在專案中運用,主要是因為kotlin的 lambda與高階函式沒有學好。這2個東西往往是一起運用的。 網上很多類似的文章都講的不夠通透,導致大部分人都卡在這裡。或者有一些人即使寫了kotlin 但是也沒用好lambda與高階函式,導致kotlin的程式碼 全是java的味道。
大家可以用一下新版本的android studio,然後新建一個kotlin語言的loginActivity,如果裡面的程式碼你能無障礙的基本看懂,那這篇文章就不用再看了,如果看起來障礙很大,那麼建議你仔細看完這篇文章,之後再返回去看這個loginActivity的程式碼,相信結果是完全不一樣的。
最後總結一下我的觀點:想寫好Kotlin的程式碼就看你對lambda與高階函式理解的有多深,早期糾結那些晦澀的語法糖沒有任何意義。
到底啥是匿名函式
那這個func 又怎麼理解呢?他為啥可以接受一個函式作為引數?
這裡有人會問了,你咋知道 這個匿名函式是沒有返回值的啊?
因為lambda表示式有一個特點,lambda括號裡面的函式最後一行就是這個函式的返回值, 圖中我們最後一行 是個print語句,這個print函式顯然是沒有返回值的,所以這個lambda 也就是這個匿名函式也就沒有了返回值了。
帶引數的lambda
然後我們反編譯看一下這段程式碼
我們換個寫法
我們再看一下反編譯的:
下面我們再改進一下寫法:
那當然還有終極的簡寫,也就是平常我們使用最多的寫法:
很多人學不好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)
}
}
複製程式碼