JAVA8函數(shù)式編程系列1--Lambda表達(dá)式

我的御姐兒?jiǎn)眩揪邮慨?dāng)初答應(yīng)你的話,現(xiàn)在開(kāi)始履行了。

一、什么是函數(shù)式編程

函數(shù)式編程的核心思想是:思考問(wèn)題時(shí),使用不可變值和函數(shù),函數(shù)對(duì)一個(gè)值進(jìn)行處理,映射成另一個(gè)值。類似于數(shù)學(xué)中的函數(shù)求值。
我們對(duì)這種思想的完全定義還為時(shí)尚早。我們現(xiàn)在想要的是如何通過(guò)使用函數(shù)式編程風(fēng)格的代碼來(lái)寫(xiě)出好代碼。
本系列將講述如何實(shí)用的使用函數(shù)式編程。幫助程序媛們(恩,沒(méi)打錯(cuò)!!!)能寫(xiě)出易讀、易維護(hù)的代碼。

下面開(kāi)始進(jìn)入正題。

二、Lambda表達(dá)式

2.1 在Android studio中使用Java8 的Lambda表達(dá)式的配置

首先,當(dāng)然需要有1.8.0以上的jdk嘍,所以別忘記了。


安裝、配置1.8.0jdk

其次,對(duì)于要使用Java8 的Lambda表達(dá)式的項(xiàng)目,對(duì)app的bulid.gradle進(jìn)行配置。

apply plugin: 'me.tatarka.retrolambda'
  //設(shè)置JDK1.8
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
app的bulid.gradle相關(guān)配置

最后,對(duì)于要使用Java8 的Lambda表達(dá)式的項(xiàng)目,在項(xiàng)目的bulid.gradle的buildscript里dependencies里進(jìn)行配置。

classpath 'me.tatarka:gradle-retrolambda:3.2.5'
項(xiàng)目的bulid.gradle相關(guān)配置

接下來(lái)我們就可以正常的使用Java8 的Lambda表達(dá)式了。


使用Java8 的Lambda表達(dá)式

2.2 初步了解Lambda表達(dá)式

我們先來(lái)看一個(gè)簡(jiǎn)單的按鈕的單擊事件,為了響應(yīng)用戶的操作,通過(guò)注冊(cè)一個(gè)事件監(jiān)聽(tīng)器。用戶一旦點(diǎn)擊按鈕,監(jiān)聽(tīng)器就會(huì)執(zhí)行相應(yīng)的操作。
btn.setOnClickListener(new Button.OnClickListener(){//創(chuàng)建監(jiān)聽(tīng)    
            public void onClick(View view) {    
              System.out.println("仁昌居士") ;
            }    
        });    
這個(gè)例子中,創(chuàng)建了一個(gè)新對(duì)象,實(shí)現(xiàn)了Button.OnClickListener接口。這個(gè)接口只有一個(gè)方法onClick(View v),當(dāng)用戶點(diǎn)擊按鈕時(shí),按鈕btn就會(huì)調(diào)用這個(gè)方法。匿名內(nèi)部類實(shí)現(xiàn)了該方法。輸出一條“仁昌居士” 的信息,表示按鈕已被點(diǎn)擊過(guò)。
使用匿名內(nèi)部類就是為了方便程序媛將代碼左邊一個(gè)代表某種行為的對(duì)象以數(shù)據(jù)的形式進(jìn)行傳遞。不過(guò),一眼所見(jiàn),匿名內(nèi)部類太冗雜了。我有用的邏輯代碼就是
  System.out.println("仁昌居士") ;
但我不得不再加上一堆樣板代碼。
為了更簡(jiǎn)單,更容易的表達(dá)程序媛們的想法,在Java 8中,就引入了Lambda表達(dá)式,這種緊湊的、傳遞行為而不是對(duì)象的方式。
可將上述匿名類的使用簡(jiǎn)化為:
btn.setOnClickListener( view ->System.out.println("仁昌居士"));    
分析這段代碼,能發(fā)現(xiàn),和傳入一個(gè)實(shí)現(xiàn)OnClickListener接口的對(duì)象不同,我們傳入的僅僅是一個(gè)函數(shù),view是參數(shù)名,和上面匿名內(nèi)部類示例中的是同一個(gè)參數(shù)。“->”就當(dāng)做指示符好吧。主題是后面的用戶點(diǎn)擊button時(shí)會(huì)運(yùn)行的一些代碼。
我們能發(fā)現(xiàn),在Lambda表達(dá)式中 view并沒(méi)有像在匿名內(nèi)部類里一樣顯式的聲明參數(shù)類型 View view,這是因?yàn)椋琷avac能夠根據(jù)程序的上下文(OnClickListener方法的簽名)在后臺(tái)推斷出參數(shù)view的類型,從而可以正常的編譯。所以對(duì)于明顯的參數(shù)類型不需要顯示聲明。**但是!**是不是就不能顯式聲明了呢?不,也可以顯示聲明的。應(yīng)為,Java  8 是靜態(tài)語(yǔ)言,編譯器有時(shí)候不能根據(jù)上下文推斷出參數(shù)的類型。所以該加的時(shí)候就加。對(duì)我個(gè)人而言,我還是喜歡顯式聲明,因?yàn)槲沂遣锁B(niǎo)嘛。

2.3 Lambda表達(dá)式的幾種表現(xiàn)形式

Lambda表達(dá)式除了基本的形式外,還有幾種不同的寫(xiě)法。
先上代碼:
public class MainActivity extends AppCompatActivity {
    private OnTestListener onTestListener;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button = (Button) findViewById(R.id.btn);
        button.setOnClickListener(view -> System.out.println("仁昌居士"));

        this.setOnTestListener(x, y -> System.out.println("仁昌居士"));

        Runnable runnable = () -> System.out.println("仁昌居士");

        Runnable runnable12 = () -> {
            System.out.println("仁昌居士");
        };

        Button.OnClickListener clickListener = view -> System.out.println("仁昌居士");

        BinaryOperator<Integer> integer = (x, y) -> x + y;

        BinaryOperator<Integer> integer2 = (Integer x, Integer y) -> x + y;
        Integer integer3 = (Integer x, Integer y) -> x + y;

    }

    public interface OnTestListener {
        void onTestClick(int x, int y);
    }

    public OnTestListener getOnTestListener() {
        return onTestListener;
    }

    public void setOnTestListener(OnTestListener onTestListener) {
        this.onTestListener = onTestListener;
    }
}
再截圖分析:
分析形式

1和2,是為了另一個(gè)注意點(diǎn),我后面會(huì)提到。
先看3,3中所示Lambda表達(dá)式實(shí)現(xiàn)了Runnable接口,該接口只有一個(gè)run方法,沒(méi)有參數(shù),返回類型為void ,寫(xiě)法上就使用"()",不包含參數(shù)。
再看4,4中所示Lambda表達(dá)式參數(shù)和3中一樣,區(qū)別在于贏了“{}”,這是用于里面的代碼是代碼塊的時(shí)候,也可以通過(guò)return和跑出異常半路退出。
接著看5,5中所示Lambda表達(dá)式僅僅只有一個(gè)參數(shù),這個(gè)時(shí)候可以選擇省略參數(shù)外的括號(hào)。
再者看6,6中所示Lambda表達(dá)式的參數(shù)是多個(gè)參數(shù)。這個(gè)時(shí)候要注意了:這行“x+y”并不是一個(gè)相加后的結(jié)果,而是一個(gè)函數(shù)操作的過(guò)程本身。
此外,可以發(fā)現(xiàn)6的這兩個(gè)參數(shù)并沒(méi)有聲明類型,那是因?yàn)長(zhǎng)ambda表達(dá)式中的參數(shù)類型都是由編譯器推斷得出的。雖然簡(jiǎn)單了,但是最好顯示聲明參數(shù)類型,如7。
接著我就要提到1,2了??戳耍?,7后發(fā)現(xiàn)賦值的類型的是BinaryOperator<T>。我如果寫(xiě)成8,則會(huì)報(bào)錯(cuò),查看原因,顯示賦值的的類型要是個(gè)接口。


需要接口

查看BinaryOperator,能夠發(fā)現(xiàn)他是個(gè)interface。


BinaryOperator是interface

所以回看1,2,為啥我可以這么寫(xiě),因?yàn)槲彝ㄟ^(guò)Lambda表達(dá)式得到的是個(gè)接口。

2.4 Lambda表達(dá)式引用的是值而不是變量

使用匿名內(nèi)部類的時(shí)候,也許會(huì)引用他所在方法里的變量,這個(gè)時(shí)候,需要將變量聲明為final。這就意味著無(wú)法再重復(fù)為其賦值,賦給該變量的是一個(gè)特定的值。

引用的變量需final

所以寫(xiě)法該是:
引用的變量是final

注意,引用的變量是final。有時(shí)候你不寫(xiě)出來(lái)也不會(huì)提示報(bào)錯(cuò),是因?yàn)槟J(rèn)給你加了final了。
Lambda表達(dá)式中也無(wú)法用非終態(tài)變量,如果使用,編譯器也會(huì)報(bào)錯(cuò)的。所以,Lambda表達(dá)式引用的其實(shí)是該變量第一次賦值的,而不是變量。
Lambda表達(dá)式引用的變量同樣是final

綜上所述,可以對(duì)Lambda表達(dá)式有一個(gè)概念:Lambda表達(dá)式是靜態(tài)類型的函數(shù)接口。

2.5 函數(shù)接口

什么是函數(shù)接口,函數(shù)接口是只有一個(gè)抽象方法的接口,用作Lambda表達(dá)式的類型。

看例子:

 public interface OnTestListener {
        void onTestClick(int x);
    }
OnTestListener只有一個(gè)抽象方法:onTestClick(onTestClick定義在OnTestListener接口中,所以默認(rèn)是抽象的,所以可以省略abstract),接受一個(gè)int 參數(shù),并返回空。
這就是使用只有一個(gè)方法的接口來(lái)表示特定的方法并能夠被反復(fù)的使用。接受的參數(shù)類型和數(shù)量,返回的類型都不重要,重要的事只有一個(gè)抽象方法。

2.6 總結(jié)

1.Lambda表達(dá)式是一個(gè)匿名的方法,傳遞一個(gè)代表某種行為的方式。
2.Lambda表達(dá)式有多種表現(xiàn)形式,常用形式:

final String name = "仁昌居士";
Button button = (Button) findViewById(R.id.btn);
 button.setOnClickListener(view -> System.out.println(name2+"喜歡御姐"));

參數(shù)變量的類型聲明可顯式可隱式。
3.Lambda表達(dá)式里引用的到的變量是final的,本質(zhì)是值,不是變量。例子如上。
4.Lambda表達(dá)式的類型是個(gè)函數(shù)接口,即僅有一個(gè)抽象方法接口。

2.7編寫(xiě)理由

Paste_Image.png

曾答應(yīng)過(guò)御姐兒要把她不懂的東西寫(xiě)成博客給她看,所以我就好好的寫(xiě)幾個(gè)系列吧,此次系列JAVA8函數(shù)式編程,會(huì)寫(xiě)完但不定期更新。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,563評(píng)論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,694評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事?!?“怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 178,672評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,965評(píng)論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,690評(píng)論 6 413
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 56,019評(píng)論 1 329
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,013評(píng)論 3 449
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 43,188評(píng)論 0 290
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,718評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,438評(píng)論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,667評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,149評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,845評(píng)論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,252評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,590評(píng)論 1 295
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,384評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,635評(píng)論 2 380

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