學(xué)習(xí) Java8 函數(shù)式編程 (二)

和 Lambda 表達(dá)式 Say Hello

如果用一大段枯燥的文字去解釋一個(gè)我們并不熟悉的概念搔预,我覺(jué)得和看天書(shū)并無(wú)區(qū)別。我之所以選擇學(xué)編程叶组,就是因?yàn)闆](méi)有什么是寫(xiě)段代碼不能搞定的拯田。那么廢話少說(shuō),大家先看看清單一中的代碼甩十。

清單一

public class Calculater {

    public static void main(String[] args) {
        final int a = 1, b = 2;
        int result = add(new IIntegerMath() {
            @Override
            public int operation() {
                return a + b;
            }
        });

        System.out.println(result);
    }

    public static int add(IIntegerMath iIntegerMath) {
        return iIntegerMath.operation();
    }

}

interface IIntegerMath {

    int operation();

}

看完清單一中的代碼船庇,估計(jì)有人要說(shuō)我了,因?yàn)檫@段代碼在上一篇博客中已經(jīng)出現(xiàn)過(guò)了侣监。但這又何妨鸭轮,通過(guò)一段簡(jiǎn)單的代碼,我們可以挖掘很多知識(shí)橄霉。在清單一代碼的 main 函數(shù)中窃爷,我調(diào)用了 add 函數(shù),并使用了一個(gè)匿名內(nèi)部類作為 add 函數(shù)的參數(shù)姓蜂。匿名內(nèi)部類被設(shè)計(jì)的目的之一就是按厘,方便程序員將代碼作為數(shù)據(jù)傳遞。

現(xiàn)在問(wèn)題來(lái)了钱慢,大家有沒(méi)有覺(jué)得這樣的代碼太過(guò)于冗余了逮京。我們明明只需要 a + b 這一條語(yǔ)句,卻附加了很多其他的代碼(命令式代碼)束莫±撩蓿可能由于大家已經(jīng)習(xí)慣了這樣的寫(xiě)法草描,但 Java8 讓我們可以用更加簡(jiǎn)單的代碼實(shí)現(xiàn)相同的功能。那么策严,我們一起來(lái)看清單二中用** Java8** 實(shí)現(xiàn)地與清單一功能相同的代碼穗慕。

清單二

public class Calculater {

    public static void main(String[] args) {
        int a = 1, b = 2;
        int result = add(() -> a + b);

        System.out.println(result);
    }

    public static int add(IIntegerMath iIntegerMath) {
        return iIntegerMath.operation();
    }

}

interface IIntegerMath {

    int operation();

}

如果有人認(rèn)為清單二中的代碼看著不爽,那么我建議他可以去泡個(gè)澡享钞,然后剪個(gè)頭發(fā)揍诽。其實(shí)清單二中的代碼我已經(jīng)在上篇博客中展示了,但我并沒(méi)有解釋 () -> a + b 是幾個(gè)意思栗竖。

我現(xiàn)在給大家分析下 () -> a + b ,其實(shí)這段代碼就是一個(gè) Lambda 表達(dá)式渠啤,也可以理解為一個(gè)函數(shù)狐肢。-> 將參數(shù)和 Lambda 表達(dá)式的主體分割開(kāi)了,-> 的左邊是參數(shù)所在的位置沥曹,() 表示無(wú)參數(shù)份名;-> 右邊的代碼是 Lambda 表達(dá)式的主體。

即使我們知道了 add 函數(shù)中那段代碼是什么意思妓美,我認(rèn)為有些人對(duì)于在 add 函數(shù)中直接傳入一個(gè) Lambda 表達(dá)式還是難以理解僵腺。那么現(xiàn)在我用另一種方式重寫(xiě)清單二中 main 函數(shù)中的代碼,請(qǐng)看清單三壶栋。

清單三

public static void main(String[] args) {
        int a = 1, b = 2;
        IIntegerMath integerMath = () -> a + b;
        int result = add(integerMath);

        System.out.println(result);
}

我相信清單三中的代碼對(duì)于大家來(lái)說(shuō)都很熟悉辰如。當(dāng)你無(wú)法理解使用 Lambda 表達(dá)式作為函數(shù)參數(shù)的用法,你們就將 Lambda 表達(dá)式理解為一個(gè)對(duì)象的引用贵试,雖然按理來(lái)說(shuō)我們不能這么來(lái)理解琉兜。

Lambda 表達(dá)式的多種形式

不帶參數(shù)的 Lambda 表達(dá)式

清單四

public class LambdaLearn {
    public static void main(String[] args) {
        INoArguments noArguments =
            () -> System.out.println("no argument");
    }
}

interface INoArguments {
    void printOperation();
}

清單四中展示了一個(gè)不帶參數(shù)的 Lambda 表達(dá)式,在 -> 的左邊使用空括號(hào) () 代表沒(méi)有參數(shù)毙玻。

帶一個(gè)參數(shù)的Lambda表達(dá)式

清單五

public class LambdaLearn {
    public static void main(String[] args) {
        IOneArguments<Integer> oneArguments =
            (a) -> a > 0;
    }
}

interface IOneArguments<T> {
    boolean assertOneNum(T argument);
}

清單五展示了一個(gè)只帶一個(gè)參數(shù)的 Lambda 表達(dá)式豌蟋,因?yàn)橹挥幸粋€(gè)參數(shù),所以參數(shù)可以用括號(hào)包裹起來(lái)桑滩,也可以不用梧疲。

帶多個(gè)參數(shù)的 Lambda 表達(dá)式

清單六

public class LambdaLearn {
    public static void main(String[] args) {
        IMultiArguments<Integer> multiArguments =
            (a, b) -> a + b;
    }
}

interface IMultiArguments<T> {
    T addOperation(T a, T b);
}

清單六中展示了一個(gè)帶多個(gè)參數(shù)的 Lambda 表達(dá)式。因?yàn)橛卸鄠€(gè)參數(shù)运准,所以需要用括號(hào)將多個(gè)參數(shù)包裹起來(lái)幌氮。

注意:我不能用慣性思維去閱讀清單六中 Lambda 表達(dá)式。該 Lambda 表達(dá)式并不是將兩個(gè)數(shù)字相加戳吝,而是創(chuàng)建了一個(gè)函數(shù)浩销,用來(lái)計(jì)算兩個(gè)數(shù)字相加的結(jié)果。變量 multiIArguments
的類型是 IMultiArguments<Integer>听哭,它不是兩個(gè)數(shù)字相加的和慢洋,而是將兩個(gè)數(shù)字相加的那行代碼塘雳。

主體用被{}包裹的 Lambda 表達(dá)式

清單七

public class LambdaLearn {
    public static void main(String[] args) {
          INoArguments multiStatement = ()  ->  {
            System.out.println("this is the first code");
            System.out.println("this is the second code");
        };
        
        INoArguments oneStatement = ()  ->  {
            System.out.println("only one code");
        };
    }
}


interface INoArguments {
    void printOperation();
}

清單七中展示了,如果 Lambda 表達(dá)式的主體有多行代碼普筹,那么就需要將多行代碼用**中括號(hào) {} **包裹败明。其實(shí)當(dāng) Lambda 表達(dá)式的主體只有一行代碼的時(shí)候,大家可以根據(jù)自己的習(xí)慣決定是否使用中括號(hào)太防。

通過(guò) Lambda 表達(dá)式來(lái)看 Java8

既成事實(shí)地final變量

在我們學(xué) Java 基礎(chǔ)的時(shí)候妻顶,我們就知道匿名內(nèi)部類只能引用外部的 final 變量。但我們卻發(fā)現(xiàn)蜒车,被 Lambda 表達(dá)式引用的外部變量并沒(méi)有被 final 修飾讳嘱。如清單八中的代碼所示,被 Lambda 表達(dá)式引用的外部變量 a 和 b 并誒有被 final 修飾酿愧,這是因?yàn)?Java8 為我們省去了一些操作沥潭,這樣代碼看上去會(huì)更加干凈舒服。雖然 a 和 b 沒(méi)有被顯示地被 final 修飾嬉挡,但它們依然是事實(shí)上的 final 變量钝鸽。你們可以根據(jù)自己的喜好,選擇性地給被 Lambda 表達(dá)式引用的外部變量加上 final 修飾符庞钢。

清單八

public static void main(String[] args) {
        int a = 1, b = 2;
        IIntegerMath integerMath = () -> a + b;
        int result = add(integerMath);

        System.out.println(result);
}

類型推斷

不知大家是否有注意拔恰,本文中使用的 Lambda 表達(dá)式都沒(méi)有為參數(shù)指明類型,這是因?yàn)?Java8 引入了比 Java7 更加強(qiáng)大的目標(biāo)類型推斷基括。如清單九中的代碼所示颜懊, Lambda 表達(dá)式的參數(shù) x 并沒(méi)有被指明類型,但 javac 會(huì)根據(jù)變量 atLeast 的類型 Predicate<Integer> 推斷出目標(biāo)類型阱穗。在日常的開(kāi)發(fā)中饭冬,請(qǐng)大家根據(jù)具體情況選擇是否給 Lambda 表達(dá)式的參數(shù)顯示地指明類型

清單九

Predicate<Integer> atLeast = x -> x > 5;

interface Predicate<Integer> {
    boolean test(T t);
}

彩蛋

其實(shí)我的微信里有關(guān)注很多技術(shù)公眾號(hào)揪阶,但真正喜歡并經(jīng)常閱讀的卻寥寥無(wú)幾昌抠,其中劉欣大神的碼農(nóng)翻身就是我非常喜歡的一個(gè)公眾號(hào)。劉欣大哥是一個(gè)有 15 年工作經(jīng)驗(yàn)的前 IBM 架構(gòu)師鲁僚,他是一個(gè)熱愛(ài)編程的資深碼農(nóng)炊苫,他用心去寫(xiě)好每一篇博客,他的每篇博客都是一個(gè)故事冰沙,他用一個(gè)個(gè)精彩短小的故事解釋有點(diǎn)枯燥的技術(shù)侨艾。下面是他公眾號(hào)的二維碼,請(qǐng)關(guān)注他拓挥,你們會(huì)收獲很多唠梨。

碼農(nóng)翻身
碼農(nóng)翻身

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市侥啤,隨后出現(xiàn)的幾起案子当叭,更是在濱河造成了極大的恐慌茬故,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蚁鳖,死亡現(xiàn)場(chǎng)離奇詭異磺芭,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)醉箕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)钾腺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人讥裤,你說(shuō)我怎么就攤上這事放棒。” “怎么了坞琴?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵哨查,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我剧辐,道長(zhǎng),這世上最難降的妖魔是什么邮府? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任荧关,我火速辦了婚禮,結(jié)果婚禮上褂傀,老公的妹妹穿的比我還像新娘忍啤。我一直安慰自己,他們只是感情好仙辟,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布同波。 她就那樣靜靜地躺著,像睡著了一般叠国。 火紅的嫁衣襯著肌膚如雪未檩。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,245評(píng)論 1 299
  • 那天粟焊,我揣著相機(jī)與錄音冤狡,去河邊找鬼。 笑死项棠,一個(gè)胖子當(dāng)著我的面吹牛悲雳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播香追,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼轧拄,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼粱挡!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起纺非,我...
    開(kāi)封第一講書(shū)人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎币励,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡岖圈,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了钙皮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜂科。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖短条,靈堂內(nèi)的尸體忽然破棺而出导匣,到底是詐尸還是另有隱情,我是刑警寧澤茸时,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布贡定,位于F島的核電站,受9級(jí)特大地震影響可都,放射性物質(zhì)發(fā)生泄漏缓待。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一渠牲、第九天 我趴在偏房一處隱蔽的房頂上張望旋炒。 院中可真熱鬧,春花似錦签杈、人聲如沸瘫镇。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)铣除。三九已至,卻和暖如春鹦付,著一層夾襖步出監(jiān)牢的瞬間尚粘,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工睁壁, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留背苦,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓潘明,卻偏偏與公主長(zhǎng)得像行剂,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子钳降,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354

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

  • Java8 in action 沒(méi)有共享的可變數(shù)據(jù)厚宰,將方法和函數(shù)即代碼傳遞給其他方法的能力就是我們平常所說(shuō)的函數(shù)式...
    鐵牛很鐵閱讀 1,229評(píng)論 1 2
  • 原文鏈接:https://github.com/EasyKotlin 值就是函數(shù),函數(shù)就是值。所有函數(shù)都消費(fèi)函數(shù)铲觉,...
    JackChen1024閱讀 5,971評(píng)論 1 17
  • 簡(jiǎn)介 概念 Lambda 表達(dá)式可以理解為簡(jiǎn)潔地表示可傳遞的匿名函數(shù)的一種方式:它沒(méi)有名稱澈蝙,但它有參數(shù)列表、函數(shù)主...
    劉滌生閱讀 3,202評(píng)論 5 18
  • 一撵幽、什么是函數(shù)式編程 下面開(kāi)始進(jìn)入正題灯荧。 二、Lambda表達(dá)式 2.1 在Android studio中使用Ja...
    仁昌居士閱讀 1,269評(píng)論 1 2
  • 美國(guó)學(xué)者做過(guò)一個(gè)細(xì)致的分析研究盐杂,下列16項(xiàng)家庭因素逗载,你覺(jué)的哪些與孩子的學(xué)習(xí)成績(jī)有關(guān),哪些無(wú)關(guān): 1.父母受過(guò)良好教...
    夢(mèng)里水飄閱讀 225評(píng)論 0 0