lambda表達式

1.lambda表達式基礎(chǔ)

?lambda表達式是一個可傳遞的代碼塊灭美,可以在以后執(zhí)行一次或多次。Java中常見的lambda表達式形式(參數(shù))铁坎、箭頭(→)以及一個表達式犁苏。如果代碼要完成的計算無法放在一個表達式中,可以使用{ }朴乖。

(String first, String second) -> 
    {
        if(first.length() < second.length) return -1;
        else if (first.length() > second.length()) return 1;
        else return 0;
    }

?即使lambda表達式沒有參數(shù)助赞,仍然要提供空括號买羞,就像無參數(shù)方法一樣雹食。

() -> { for (int i = 100; i > = 0; i--) System.out.println(i);}

?如果可以推導(dǎo)出一個lambda表達式的參數(shù)類型,則可以忽略其類型吃挑。例如:

Comparator<String> comp = (first, second) -> first.length() - second.length();

?如果方法只有一個參數(shù)街立,而且這個參數(shù)的類型可以推導(dǎo)得出,還可以省略小括號

ActionListener listener = event -> System.out.println("The time is");

?無需指定lambda表達式的返回類型逛犹。lambda表達式的返回類型總是會由上下文推導(dǎo)得出梁剔。


2.lambda表達式轉(zhuǎn)換成函數(shù)式接口

?對于只有一個抽象方法的接口,需要這種接口的對象時,就可以提供一個lambda表達式喷鸽。這種接口稱為函數(shù)式接口

?為了展示如何轉(zhuǎn)換為函數(shù)式接口砾省,下面考慮Arrays.sort方法。它的第二個參數(shù)需要一個Comparator實例轩性,Comparator就是只有一個方法的接口狠鸳,所以可以提供一個lambda表達式件舵,最好把lambda表達式看作是一個函數(shù)而不是一個對象

Arrays.sort(words, (first, second) -> first.length() - second.length());

?使用lambda表達式的重點是延遲執(zhí)行铅祸,需要清楚了解函數(shù)式接口參數(shù)類型临梗、參數(shù)個數(shù)以及返回值類型,才能更好的使用lambda表達式盟庞。

?來看一個簡單的例子茫经。假設(shè)想要重復(fù)一個動作n次。將這個動作和重復(fù)次數(shù)傳遞到一個repeat方法:

repeat(10, ()-> System.out.println("Hello, World!"));

要接受這個lambda表達式抹镊,需要選擇一個函數(shù)式接口荤傲。這里提供Runnable接口:

public static void repeat(int n, Runnable action) {
      for (int i = 0; i < n; i++) action.run;
}

當調(diào)用action.run()時會執(zhí)行這個lambda表達式的主體。

?下面給出JavaAPI中提供的最重要的函數(shù)式接口:
Java函數(shù)式接口.jpg

?有時可能需要自己設(shè)計接口终佛,若其中只有一個抽象方法雾家,可以用@FunctionalInterdace注釋來標記這個接口芯咧。在javadoc頁里會指出你的接口是一個函數(shù)式接口竹揍。


3.lambda表達式實現(xiàn)方法引用

?有時邪铲,可能已經(jīng)有現(xiàn)成的方法可以完成你想要傳遞到其他代碼的某個動作,可以對已有的方法進行引用
?主要有3種情況

  • object::instanceMethod 對象的實例方法
  • Class::staticMethod 類的靜態(tài)方法
  • Class::instanceMethod 類的實例方法
    ?例:
//正常寫法昧碉,匿名類
 mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                v.getId();
            }
        });

  //lambda表達式
  mButton.setOnClickListener(v-> v.getId());

  //類的實例方法引用  ---  (view, args)->view.getId(args)
  mButton.setOnClickListener(View::getId);

  //對象的實例方法引用 --- (view)->viewGroup.addView(view)
  mButton.setOnClickListener(viewGroup::addView);

  //類的靜態(tài)方法引用 --- (view)-> MyTest.getId(view);
  mButton.setOnClickListener(MyTest::getId);
 
  public class MyTest {
    public static void getId(View view) {}
}

?對于Class::instanceMethod被饿,第一個參數(shù)會成為方法的隱式參數(shù)永丝,第二個參數(shù)(假如有)會成為顯式參數(shù)

?對于object::instanceMethodClass::staticMethod哥牍,方法引用等價于提供方法參數(shù)的lambda表達式喝检。即lambda表達式的參數(shù)成為所引用方法的顯示參數(shù)

?特別注意:可以在方法引用中使用this和super參數(shù)澡谭。

this::equals 等同于  x-> this.equals(x) 

super::instanceMethod 會調(diào)用給定方法的超類版本

4.構(gòu)造器引用

?構(gòu)造器引用與方法引用類似损俭,只不過方法名為new杆兵。

Person::new是Person構(gòu)造器的一個引用,具體調(diào)用哪個構(gòu)造器攒砖,取決于上下文

int[ ]::new是一個構(gòu)造器引用日裙,它有一個參數(shù):即數(shù)組的長度。等價于 x->new int[x]

5.lambda表達式中變量的作用域

?通常昂拂,我們希望能夠在lambda表達式訪問外圍方法或類中的變量

public static void repeatMessage(String text, int delay) {
    ActionListener listener = event -> {
          System.out.println(text);
          Toolkit.getDefaultTookit().beep();
      };
     new Timer(delay, listener).start();
}

?lambda表達式中的變量text路克,并不是在這個lambda表達式中定義的精算。lambda表達式可能會在repeatMessage調(diào)用返回很久后才開始運行碎连,而那時候text這個變量參數(shù)可能已經(jīng)不存在了。

?實際上廉嚼,lambda表達式3部分組成:

  • 一個代碼塊
  • 參數(shù)
  • 自由變量的值倒戏,指非參數(shù)而且不再代碼中定義的變量。
    ?可以看到傍念,lambda表達式可以捕獲外圍作用域中變量的值葛闷。lambda表達式中捕獲的變量必須是最終變量,即這個變量初始化后就不會再改變淑趾。

?在一個lambda表達式中使用this關(guān)鍵字阳仔,是指創(chuàng)建這個lambda表達式方法this參數(shù)

public class Application() {
    public void init() {
      ActionListener listener = event -> {
            System.out.println(this.toString());
         }
    }
}

?表達式this.toString()調(diào)用Application對象的toString方法扣泊,而不是ActionListener實例的方法近范。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市延蟹,隨后出現(xiàn)的幾起案子评矩,更是在濱河造成了極大的恐慌,老刑警劉巖等孵,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件稚照,死亡現(xiàn)場離奇詭異,居然都是意外死亡俯萌,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門咐熙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弱恒,“玉大人,你說我怎么就攤上這事棋恼》档” “怎么了锈玉?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長义起。 經(jīng)常有香客問我拉背,道長,這世上最難降的妖魔是什么默终? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任椅棺,我火速辦了婚禮,結(jié)果婚禮上齐蔽,老公的妹妹穿的比我還像新娘两疚。我一直安慰自己,他們只是感情好含滴,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布诱渤。 她就那樣靜靜地躺著,像睡著了一般谈况。 火紅的嫁衣襯著肌膚如雪勺美。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天鸦做,我揣著相機與錄音励烦,去河邊找鬼。 笑死泼诱,一個胖子當著我的面吹牛坛掠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播治筒,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼屉栓,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了耸袜?” 一聲冷哼從身側(cè)響起友多,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎堤框,沒想到半個月后域滥,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡蜈抓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年启绰,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沟使。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡委可,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出腊嗡,到底是詐尸還是另有隱情着倾,我是刑警寧澤拾酝,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站卡者,受9級特大地震影響蒿囤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜崇决,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一蟋软、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嗽桩,春花似錦、人聲如沸凄敢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽涝缝。三九已至扑庞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拒逮,已是汗流浹背罐氨。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留滩援,地道東北人栅隐。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像玩徊,于是被迫代替她去往敵國和親租悄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355