Kotlin 學(xué)習(xí)筆記: lambda編程

Kotlin學(xué)習(xí)筆記:概述
Kotlin學(xué)習(xí)筆記:基本語(yǔ)法和函數(shù)
Kotlin學(xué)習(xí)筆記:類和接口
Kotlin學(xué)習(xí)筆記:lambda編程
Kotlin學(xué)習(xí)筆記:類型系統(tǒng)
Kotlin學(xué)習(xí)筆記:泛型
Kotlin學(xué)習(xí)筆記:注解和反射

什么是lambda表達(dá)式

“Lambda 表達(dá)式”(lambda expression)是一個(gè)匿名函數(shù)曙蒸,Lambda表達(dá)式基于數(shù)學(xué)中的λ演算得名,直接對(duì)應(yīng)于其中的lambda抽象(lambda abstraction)刺彩,是一個(gè)匿名函數(shù)说莫,即沒(méi)有函數(shù)名的函數(shù)屁柏。
lambda表達(dá)式本質(zhì)上是可以傳遞給其他函數(shù)的一段代碼滴铅。lambda可以作為函數(shù)的參數(shù)和返回值瓮钥。大大簡(jiǎn)化了代碼底桂。

lambda表達(dá)式的語(yǔ)法為

image.png

集合的函數(shù)式API

  • filter

filter 可以移除集合中不滿足條件的元素式散。

>>> val list = listOf(1, 2, 3, 4)
>>> list.filter { it % 2 == 0 }
[2, 4]
image.png
  • map

map函數(shù)對(duì)集合中的每個(gè)元素應(yīng)用給定的函數(shù)并把結(jié)果收集到一個(gè)集合中筋遭。

>>> val list = listOf(1, 2, 3, 4)
>>> list.map { it * it }
[1, 4, 9, 16]
image.png
  • all,any暴拄,find漓滔,count

這些主要用于對(duì)集合的判定

假如我們需要判定一群人中的年齡是否小于28歲

val canBeInClub27 = { p: Person -> p.age <= 27 }

使用all判定是否所有人都小于28歲

>>> val people = listOf(Person("Alice", 27), Person("Bob", 31))
>>> println(people.all(canBeInClub27))
false

使用any判定其中的一些人小于28歲

>>> println(people.any(canBeInClub27))
true

使用count計(jì)算小于28歲的人的個(gè)數(shù)

>>> val people = listOf(Person("Alice", 27), Person("Bob", 31))
>>> println(people.count(canBeInClub27))
1

使用find找到所有小于28歲的人信息

>>> val people = listOf(Person("Alice", 27), Person("Bob", 31))
>>> println(people.find(canBeInClub27))
Person(name=Alice, age=27)
  • groupBy

groupBy可以用于將列表轉(zhuǎn)換成分組的map

>>> val people = listOf(Person("Alice", 31),
... Person("Bob", 29), Person("Carol", 31))
>>> println(people.groupBy { it.age })
image.png
  • flatmap和flatten

flatMap函數(shù)做兩件事情:首先根據(jù)作為實(shí)參給定的函數(shù)對(duì)集合中的每個(gè)元素做變換(maps),然后把多個(gè)列表合并(flatten)成一個(gè)列表乖篷。

>>> val strings = listOf("abc", "def")
>>> println(strings.flatMap { it.toList() })
[a, b, c, d, e, f]
image.png

flatten可以將多個(gè)集合的元素合并到一個(gè)集合中响驴。

>>>  val langs = listOf(listOf("js"), listOf("Java", "Kotlin"), listOf("C++", "PHP", "Python"))
>>> println(langs.flatten())
[js, Java, Kotlin, C++, PHP, Python]

序列

前面講述了很多鏈?zhǔn)郊险{(diào)用的例子,但是這些函數(shù)會(huì)及早的創(chuàng)建中間集合撕蔼,也就是說(shuō)每一步的中間結(jié)果都存儲(chǔ)在一個(gè)臨時(shí)列表里豁鲤。所以,當(dāng)直接使用鏈?zhǔn)郊系暮瘮?shù)處理集合元素?cái)?shù)量特別多的情況下鲸沮,性能比較低琳骡。而序列可以避免創(chuàng)建臨時(shí)中間變量。

舉例來(lái)講

有一個(gè)Person類讼溺,它有名字和年齡兩個(gè)屬性楣号。

data class Person(val name: String, val age:Int)

要找出名字前綴是“J”的人的姓名

用鏈?zhǔn)郊虾瘮?shù)

persons.map { person -> person.name }
            .filter { it.startsWith("J") }
            .toList()

編譯代碼,再將其反編譯

    //....
    Object element$iv$iv;
      while(var4.hasNext()) {
         element$iv$iv = var4.next();
         Person person = (Person)element$iv$iv;
         String var11 = person.getName();
         destination$iv$iv.add(var11);
      }
    //...   

用序列實(shí)現(xiàn)

 persons.asSequence()
            .map { person -> person.name }
            .filter { it.startsWith("J") }
            .toList()

反編譯后代碼

List persons = CollectionsKt.listOf(new Person[]{new Person("Jack", 25), new Person("Cat", 29)}); 
SequencesKt.toList(SequencesKt.filter(SequencesKt.map(CollectionsKt.asSequence((Iterable)persons), (Function1)null.INSTANCE), (Function1)null.INSTANCE));

使用Java函數(shù)式接口

首先說(shuō)函數(shù)式接口的定義:只有一個(gè)抽象方法的接口稱為函數(shù)式接口怒坯,也就是SAM(單抽象方法)炫狱。

在Android中,最常用的接口就是OnClickListener了【炊牵現(xiàn)在我們以監(jiān)聽一個(gè)button的點(diǎn)擊事件為例毕荐,來(lái)說(shuō)明kotlin是如何使用Java函數(shù)式接口的。

用java編寫監(jiān)聽button點(diǎn)擊事件

    btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {...}
        });

用kotlin編寫button點(diǎn)擊事件

btn.setOnClickListener{...}

我們還記得在函數(shù)文章中艳馒,我們用過(guò)匿名表達(dá)式憎亚。

  val vto = layout.viewTreeObserver
        vto.addOnGlobalLayoutListener(object: ViewTreeObserver.OnGlobalLayoutListener       {
            @RequiresApi(Build.VERSION_CODES.JELLY_BEAN)
            override fun onGlobalLayout(){
                layout.viewTreeObserver.removeOnGlobalLayoutListener(this)
                val height = layout.measuredHeight
                val width = layout.measuredWidth
            }
        })

OnGlobalLayoutListener接口也只有一個(gè)方法,符合函數(shù)式接口的定義弄慰。那么第美,這個(gè)方法可以用lambda簡(jiǎn)化嗎?答案是不可以陆爽。因?yàn)榘?code>layout.viewTreeObserver.removeOnGlobalLayoutListener(this)語(yǔ)句什往。

在lambda 內(nèi)部沒(méi)有匿名對(duì)象那樣的this。這意味著沒(méi)有辦法引用到lambda轉(zhuǎn)換成的匿名類實(shí)例慌闭。

帶接收者的lambda:with和apply

很多語(yǔ)言都有這樣的語(yǔ)句:可以用他們對(duì)同一個(gè)對(duì)象執(zhí)行多次操作别威,而不需要把對(duì)象的名稱寫出來(lái)躯舔。

with 和apply就是這樣的語(yǔ)句搂橙。

  • with

還是以一個(gè)例子開始:創(chuàng)建一個(gè)函數(shù)打印字母表髓迎。

一般情況下,都這樣寫

fun alphabet(): String {
    val result = StringBuilder()
    for (letter in 'A'..'Z') {
        result.append(letter)
    }
    result.append("\nNow I know the alphabet!")
    return result.toString()
} 
>>> println(alphabet())
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Now I know the alphabet!

而用with叛买,可以這樣寫

fun alphabet(): String {
    val result = StringBuilder()
    return with(result)
        { for (letter in 'A'..'Z')
            {this.append(letter)}
            append("\nNow I know the alphabet!")
            this.toString()
        }
    }
  • apply

apply幾乎和with一模一樣豺妓,唯一的區(qū)別是apply始終會(huì)返回作為實(shí)參傳遞給他的對(duì)象惜互。

fun alphabet() = StringBuilder().apply{ 
    for (letter in 'A'..'Z') {
        append(letter)
    }
    append("\nNow I know the alphabet!")
}.toString()

高階函數(shù)

高階函數(shù):以另一個(gè)函數(shù)作為參數(shù)或者返回值的函數(shù)。

  • 函數(shù)類型

為了聲明一個(gè)以lambda作為實(shí)參的函數(shù)琳拭,需要知道如何聲明對(duì)應(yīng)的形參類型训堆。

語(yǔ)法:將函數(shù)參數(shù)類型放在括號(hào)中,緊接著是一個(gè)箭頭和函數(shù)的返回類型

  • 調(diào)用作為參數(shù)的函數(shù)類型
fun searchRepos(
        service: ZhihuService,
        query:String,
        onSuccess:(repos: List<Repo>) -> Unit,
        onError: (error: String) -> Unit) {
   //...
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末白嘁,一起剝皮案震驚了整個(gè)濱河市坑鱼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌絮缅,老刑警劉巖姑躲,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異盟蚣,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)卖怜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門屎开,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人马靠,你說(shuō)我怎么就攤上這事奄抽。” “怎么了甩鳄?”我有些...
    開封第一講書人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵逞度,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我妙啃,道長(zhǎng)档泽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任揖赴,我火速辦了婚禮馆匿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘燥滑。我一直安慰自己渐北,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開白布铭拧。 她就那樣靜靜地躺著赃蛛,像睡著了一般恃锉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上呕臂,一...
    開封第一講書人閱讀 49,821評(píng)論 1 290
  • 那天破托,我揣著相機(jī)與錄音,去河邊找鬼诵闭。 笑死炼团,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的疏尿。 我是一名探鬼主播瘟芝,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼褥琐!你這毒婦竟也來(lái)了锌俱?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤敌呈,失蹤者是張志新(化名)和其女友劉穎贸宏,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體磕洪,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吭练,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了析显。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鲫咽。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖谷异,靈堂內(nèi)的尸體忽然破棺而出分尸,到底是詐尸還是另有隱情,我是刑警寧澤歹嘹,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布箩绍,位于F島的核電站,受9級(jí)特大地震影響尺上,放射性物質(zhì)發(fā)生泄漏材蛛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一尖昏、第九天 我趴在偏房一處隱蔽的房頂上張望仰税。 院中可真熱鬧,春花似錦抽诉、人聲如沸陨簇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)河绽。三九已至己单,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間耙饰,已是汗流浹背纹笼。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留苟跪,地道東北人廷痘。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像件已,于是被迫代替她去往敵國(guó)和親笋额。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • 寫在開頭:本人打算開始寫一個(gè)Kotlin系列的教程篷扩,一是使自己記憶和理解的更加深刻兄猩,二是可以分享給同樣想學(xué)習(xí)Kot...
    胡奚冰閱讀 1,236評(píng)論 0 6
  • lambda即lambda表達(dá)式,簡(jiǎn)稱lambda鉴未。本質(zhì)上是可以傳遞給其它函數(shù)的一小段代碼枢冤。有了lambda,可以...
    程自舟閱讀 16,077評(píng)論 1 26
  • 定義 Lambda表達(dá)式铜秆,本質(zhì)上就是可以傳遞其他函數(shù)的一小段代碼淹真。有了lambda,可以輕松的把通用的代碼結(jié)構(gòu)抽取...
    m1Ku閱讀 525評(píng)論 0 0
  • 原文鏈接:https://github.com/EasyKotlin 值就是函數(shù),函數(shù)就是值连茧。所有函數(shù)都消費(fèi)函數(shù)趟咆,...
    JackChen1024閱讀 5,957評(píng)論 1 17
  • 教師的假期,不光是休整身體梅屉,更是一個(gè)充電的好機(jī)會(huì)。我們要有終身學(xué)習(xí)的精神鳞贷。從7月29日-8月4日坯汤,我將參加長(zhǎng)洲區(qū)校...
    歐潔蘭閱讀 411評(píng)論 0 0