Java8_Lambda表達(dá)式初識(shí)

Lambda表達(dá)式到底是什么


讓我們從一個(gè)最常用的例子說起芹橡,Java8之前我們循環(huán)一個(gè)List的時(shí)候一般會(huì)這樣寫:

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8);
        
for(Integer integer : list){
    System.out.println(integer);
}

在Java8中我們可以這樣寫:

第一種:
list.forEach(new Consumer<Integer>() {
    @Override
    public void accept(Integer integer) {
        System.out.println(integer);
    }
});

是不是看起來好像更繁瑣了呢毒坛,別著急,我們繼續(xù)變化一下:

第二種:
list.forEach(integer -> {System.out.println(integer);});

這里就是使用了Lambda表達(dá)式林说,
我們進(jìn)入forEach方法的源碼來看一下:

default void forEach(Consumer<? super T> action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }
}

方法的參數(shù)是一個(gè)Consumer煎殷,我們來看看這個(gè)Consumer

/**
 * @since 1.8
 */
@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);
}

Consumer是Java8開始提供的一個(gè)接口,我們看到這個(gè)接口有一個(gè)注解@FunctionalInterface腿箩,使用這個(gè)注解的接口被稱為“函數(shù)式接口”豪直,我們來看下什么叫函數(shù)式接口:

函數(shù)式接口 FunctionalInterface
1.如果一個(gè)接口只有一個(gè)抽象方法,那么該接口就是一個(gè)函數(shù)式接口
2.如果我們?cè)谀硞€(gè)接口上聲明了FunctionalInterface注解珠移,那么編譯器就會(huì)按照函數(shù)式是接口的要求該接口
3.如果某個(gè)接口只有一個(gè)抽象方法弓乙,但我們并沒有給該接口聲明FunctionalInterface注解末融,那么編譯器依舊會(huì)將該接口看作是函數(shù)式接口

4.Note that instances of functional interfaces can be created with lambda expressions, method references, or constructor references.
 一個(gè)函數(shù)式接口的實(shí)例對(duì)象可以使用lambda表達(dá)式、方法引用暇韧、構(gòu)造方法來創(chuàng)建

這里提到了lambda表達(dá)式勾习,這里就解釋了為什么本文一開始第一種寫法到第二種寫法的轉(zhuǎn)變。使用integer -> {System.out.println(integer);}lambda表達(dá)式來創(chuàng)建Consumer這個(gè)函數(shù)式接口懈玻。

接觸過js之類語言的同學(xué)肯定很眼熟巧婶,在js中函數(shù)參數(shù)是一個(gè)函數(shù),返回值是另一個(gè)函數(shù)是很常見的酪刀,但是在之前的Java中我們無法將函數(shù)作為一個(gè)參數(shù)傳遞給一個(gè)方法,也無法聲明返回一個(gè)函數(shù)的方法钮孵。

為此Java8引入了Lambda表達(dá)式來提供這種方法骂倘,integer -> {System.out.println(integer);}在這里作為參數(shù),傳遞給 forEach 方法巴席,我們可以把這理解為是一種“行為”历涝,我們是把一種“行為”傳遞給這個(gè)方法,這樣做提升了抽象層次漾唉,使得API重用性更好荧库,更加靈活。

Lambda表達(dá)式的結(jié)構(gòu)


一個(gè)Lambda表達(dá)式主要有以下部分組成:參數(shù)列表赵刑,箭頭(->)分衫,以及一個(gè)表達(dá)式或語句塊。
 (arg1,arg2) -> {body}
  1. 一個(gè)Lambda表達(dá)式可以有零個(gè)或多個(gè)參數(shù)般此,參數(shù)在圓括號(hào)里蚪战,參數(shù)之間逗號(hào)分隔;

  2. 空?qǐng)A括號(hào)代表參數(shù)集為空;

  3. 當(dāng)只有一個(gè)參數(shù),且其類型可推導(dǎo)時(shí)铐懊,圓括號(hào)()可省略

    (x,y) -> {return x + y}
    () -> {return x + y}
    x -> x*x
    
  4. 參數(shù)的類型既可以明確聲明邀桑,也可以根據(jù)上下文來推斷

    不聲明:(x,y) -> {return x+y;}
    聲明:(int x,int y) -> {return x+y;}
    
    
  5. 如果Lambda表達(dá)式的主體只有一條語句,花括號(hào){}可以省略科乎。匿名函數(shù)的返回類型與該主體表達(dá)式一致

  6. 如果是一條語句以上壁畸,表達(dá)式必須放在華括號(hào){}里(形成代碼塊)

    省略前:(int x,int y) -> {return x + y;}
    省略后:(int x,int y) -> x + y
    

常用的Lambda表達(dá)式


  1. Consumer :

/**
* Consumer
* 接收一個(gè)參數(shù)不返回
* void accept(T t);
*/
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
list.forEach(integer -> { System.out.println(integer); });
  1. Function:
/**
* Function
* 接收一個(gè)參數(shù),返回一個(gè)值
* R apply(T t);
*/
int result = test.calc(5, value -> value * value); //25
int result2 = test.calc(5, value -> value - 2); //3

    
public int calc(int a,Function<Integer,Integer> function){
    return function.apply(a);
}

3.BiFunction

/**
 * BiFunction
 * 接收兩個(gè)參數(shù)茅茂,返回一個(gè)值
 * R apply(T t, U u);
 */
int result1 = test.calc(3, 4, (a, b) -> a + b);//7
int result2 = test.calc(3, 4, (a, b) -> a * b);//12


public int calc(int a, int b, BiFunction<Integer, Integer, Integer> biFunction) {
    return biFunction.apply(a, b);
}
  
  1. Comparator
  /**
 * Comparator
 * 接收兩個(gè)參數(shù)捏萍,返回int
 * int compare(T o1, T o2);
 */
List<Integer> list = Arrays.asList(6,2, 8, 5, 9, 1, 4, 3);
Collections.sort(list,(a,b) -> a.compareTo(b));
list.forEach(item-> System.out.print(item));//12345689

5.Predicate

/**
 * Predicate
 * 接收一個(gè)參數(shù),返回布爾值
 * boolean test(T t);
 */
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
Predicate<Integer> p1 = value -> value % 2 == 0;
Predicate<Integer> p2 = value -> value > 5;
list.stream().filter(p1).collect(Collectors.toList()).forEach(item -> System.out.print(item));//2468
list.stream().filter(p1.and(p2)).collect(Collectors.toList()).forEach(item -> System.out.print(item));//68

6.Supplier

/**
 * Supplier
 * 不接收參數(shù)返回一個(gè)值
 * T get();
 */
Supplier<Student> supplier = () -> new Student();
Student student = supplier.get();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末空闲,一起剝皮案震驚了整個(gè)濱河市照弥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌进副,老刑警劉巖这揣,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悔常,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡给赞,警方通過查閱死者的電腦和手機(jī)机打,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來片迅,“玉大人残邀,你說我怎么就攤上這事「躺撸” “怎么了芥挣?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)耻台。 經(jīng)常有香客問我空免,道長(zhǎng),這世上最難降的妖魔是什么盆耽? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任蹋砚,我火速辦了婚禮,結(jié)果婚禮上摄杂,老公的妹妹穿的比我還像新娘坝咐。我一直安慰自己,他們只是感情好析恢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布墨坚。 她就那樣靜靜地躺著,像睡著了一般映挂。 火紅的嫁衣襯著肌膚如雪框杜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天袖肥,我揣著相機(jī)與錄音咪辱,去河邊找鬼。 笑死椎组,一個(gè)胖子當(dāng)著我的面吹牛油狂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播寸癌,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼专筷,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了蒸苇?” 一聲冷哼從身側(cè)響起磷蛹,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎溪烤,沒想到半個(gè)月后味咳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體庇勃,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年槽驶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了责嚷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡掂铐,死狀恐怖罕拂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情全陨,我是刑警寧澤爆班,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站辱姨,受9級(jí)特大地震影響柿菩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜炮叶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一碗旅、第九天 我趴在偏房一處隱蔽的房頂上張望渡处。 院中可真熱鬧镜悉,春花似錦、人聲如沸医瘫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)醇份。三九已至稼锅,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間僚纷,已是汗流浹背矩距。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留怖竭,地道東北人锥债。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像痊臭,于是被迫代替她去往敵國(guó)和親哮肚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

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

  • lambda表達(dá)式(又被成為“閉包”或“匿名方法”)方法引用和構(gòu)造方法引用擴(kuò)展的目標(biāo)類型和類型推導(dǎo)接口中的默認(rèn)方法...
    183207efd207閱讀 1,481評(píng)論 0 5
  • 原文鏈接: Lambdas 原文作者: shekhargulati 譯者: leege100 lambda表達(dá)式是...
    忽來閱讀 6,587評(píng)論 8 129
  • 聲明:本文翻譯自The Java? Tutorials(官方文檔) 簡(jiǎn)述 匿名類有一個(gè)問題广匙,如果匿名類的實(shí)現(xiàn)非常簡(jiǎn)...
    猴子小皮球閱讀 4,657評(píng)論 0 9
  • 簡(jiǎn)介 概念 Lambda 表達(dá)式可以理解為簡(jiǎn)潔地表示可傳遞的匿名函數(shù)的一種方式:它沒有名稱允趟,但它有參數(shù)列表、函數(shù)主...
    劉滌生閱讀 3,202評(píng)論 5 18
  • 為了支持函數(shù)式編程鸦致,Java 8引入了Lambda表達(dá)式.在Java 8中采用的是內(nèi)部類來實(shí)現(xiàn)Lambda表達(dá)式....
    光劍書架上的書閱讀 959評(píng)論 2 10