java8-01-lambda

[TOC]

0 lambda的傳說

其實我也沒法說清楚他到底是什么鬼……

就好比你沒見過某種顏色富蓄,我再怎么描述都沒法描述清楚官边,還是親自看看他長啥樣吧


還記得中學(xué)的時候谁鳍,數(shù)學(xué)里經(jīng)常出現(xiàn)的那個符號嗎?

先放一個從百度圖庫偷來的圖片(CSDN打上的水印歼跟,不關(guān)我事哈……)

lambda

就是這貨轩性,此處的lambda 就是它……

傳說中這玩意兒是比程序員還瘋狂的數(shù)學(xué)家的口頭禪……

上面的廢話都看完了声登??揣苏?悯嗓?

雖然見到了他,但是還是不清楚他到底是什么……

好了舒岸,不扯皮了绅作,開講啦


  • 百科里是這么描述的:

Lambda 表達(dá)式”是一個匿名函數(shù),可以包含表達(dá)式和語句蛾派,并且可用于創(chuàng)建委托或表達(dá)式目錄樹類型俄认。

看百科的描述好像有那么點感覺了『檎В可是干嘛非要搞個這么高冷的解釋呢眯杏?

  • 個人是這么理解的:

lambda 類似于一個可調(diào)用的代碼塊或者游離函數(shù)。當(dāng)然也可以有入?yún)ⅰ?/p>

1 瞄一眼他長啥樣?

  • 示例

比如下面這樣:

Comparator<Integer> c = (i, j) -> Integer.compare(i, j);

等價的原始Java代碼長這樣:

Comparator<Integer> c = new Comparator<Integer>() {
  @Override
  public int compare(Integer o1, Integer o2) {
    return Integer.compare(o1, o2);
  }
};

用上lambda是什么體驗壳澳?

  • 代碼量好像少了
  • 逼格好像提高了
  • 代碼好像更優(yōu)雅了

2 lambda各種外觀

至少在Java里lambda的爸爸媽媽姐姐弟弟爺爺奶奶七大姑八大姨……可能都是長這個樣子的岂贩。

同時,據(jù)老夫多年的斷案經(jīng)驗來推斷巷波,lambda的本尊應(yīng)該也是這個樣子的:

(Type1 param1,Type2 param2, ...) -> {
  // 一些亂七八糟萎津、烏漆嘛黑的處理操作();
  return ret;
}
  • 外觀一:沒有入?yún)⒌臅r候
()->{return ret;}
  • 外觀二:有參數(shù)的時候
(Type p)->{return ret;}

// 參數(shù)類型可以省略(隱式推掉)
(p)->{return ret;}

// 一個參數(shù)的時候卸伞,參數(shù)列表外的括號也可以沒有
p->{return ret;}
  • 外觀三:函數(shù)體只有一行的時候
// 方法體只有一行的時候,或括號連同結(jié)尾的分號都可以省略
e->ret
  • 外觀四:沒有返回值的時候
e->{}
  • 方法引用和構(gòu)造器引用
    • instance::instanceMethod
    • className::staticMethod
    • className::instanceMethod
Arrays.asList(null, "", "   ", "HelloWorld", "ByeBug")//
  .stream().filter(StringUtils::isNotBlank)//
  .forEach(System.out::println);
  • ……

3 lambda使用場景

再看一個例子:

// 原始方法啟動一個線程
new Thread(new Runnable() {
  @Override
  public void run() {
  }
}).start();

// lambda版
new Thread(()->{}).start();

不難看出,整個匿名內(nèi)部類中最關(guān)鍵的代碼其實就是:

public void run() {
}

所以锉屈,lambda中關(guān)鍵部分也就是這部分代碼了荤傲。

其實,用注解java.lang.FunctionalInterface修飾的接口都可以用于lambda表達(dá)式中颈渊。

這種接口遂黍,都是只有一個方法的接口。

另外俊嗽,只要你的接口只有一個方法雾家,即使是沒有@FunctionalInterface注解修飾,也是可以用lambda的(很多時候編譯器還是很聰明的,他會自動推斷的)。

總之绍豁,lambda只鐘愛函數(shù)式接口(@FunctionalInterface)芯咧。


4 再來個示例

public class HouseInfo {

    private Integer houseId; // 小區(qū)ID
    private String houseName;// 小區(qū)名
    private Integer browseCount; // 瀏覽數(shù)
    private Integer distance;// 距離 KM
    // constructor
    // getters
    // setters
}
  • 有如下數(shù)據(jù)
List<HouseInfo> houseInfos = Lists.newArrayList(//
    new HouseInfo(1, "恒大星級公寓", 100, 1), //
    new HouseInfo(2, "匯智湖畔", 999, 2), //
    new HouseInfo(3, "張江湯臣豪園", 100, 1), //
    new HouseInfo(4, "保利星苑", 23, 10), //
    new HouseInfo(5, "北顧小區(qū)", 66, 23), //
    new HouseInfo(6, "北杰公寓", null, 55), //
    new HouseInfo(7, "保利星苑", 77, 66), //
    new HouseInfo(8, "保利星苑", 111, 12)//
);
  • 按距離排序
Collections.sort(houseInfos, (h1, h2) -> {
    if (h1 == null || h2 == null)
      return 0;
    if (h1.getDistance() == null || h2.getDistance() == null)
      return 0;
    return h1.getDistance().compareTo(h2.getDistance());
});
  • 輸出小區(qū)名
houseInfos.stream().map(h -> h.getHouseName()).forEach(System.out::println);
  • 動態(tài)條件過濾
// 該函數(shù)式接口用來當(dāng)做測試條件
public static interface Condition<T> {
  boolean conditionTest(T e);
}

// 定義一個方法來輸出滿足condition測試結(jié)果的小區(qū)
public void printWithFilter(List<HouseInfo> houseList, Condition<HouseInfo> condition) {
  houseList.stream().filter(e -> condition.conditionTest(e)).forEach(System.out::println);
}

@Test
public void test4() {
  List<HouseInfo> houseInfos = Lists.newArrayList(//
    new HouseInfo(1, "恒大星級公寓", 100, 1), //
    new HouseInfo(2, "匯智湖畔", 999, 2), //
    new HouseInfo(3, "張江湯臣豪園", 100, 1), //
    new HouseInfo(4, "保利星苑", 23, 10), //
    new HouseInfo(5, "北顧小區(qū)", 66, 23), //
    new HouseInfo(6, "北杰公寓", null, 55), //
    new HouseInfo(7, "保利星苑", 77, 66), //
    new HouseInfo(8, "保利星苑", 111, 12)//
  );
  // 打印小區(qū)名包含北字的小區(qū)
  printWithFilter(houseInfos, e -> e != null && e.getHouseName().contains("北"));
  // 打印距離大于10KM的小區(qū)
  printWithFilter(houseInfos, e -> e != null && e.getDistance() != null && e.getDistance() > 10);
}
  • 字符串轉(zhuǎn)大寫
Arrays.asList("HelloWord", "ByeBug")
  .stream().map(String::toUpperCase).forEach(System.out::println);
  • 其實在Scala里lambda更加直觀
List("HelloWord", "ByeBug").map(_.toUpperCase()).foreach(println _);

5 lambda的好基友

通過上面的示例,再結(jié)合實際妹田。不難發(fā)現(xiàn)最常用的lambda的形式如下:

  • 單個輸入唬党,無輸出
  • 單個輸入鹃共,單個輸出
  • 無輸入鬼佣,輸出單個類型
  • 兩個不同類型的輸入,第三種類型的輸出
  • 兩個不同類型的輸入霜浴,其中一種類型的輸出
  • ……

其實在每次使用的時候晶衷,沒必要自己去新建這些函數(shù)式接口以支持lambda,JDK就已經(jīng)給lambda內(nèi)置了很多好基友:

  • Consumer: 單個輸入阴孟,無輸出
public interface Consumer<T> {
  void accept(T t);
}
  • BiConsumer: 兩個不同類型的輸入晌纫,無輸出
public interface BiConsumer<T, U> {
  void accept(T t, U u);
}
  • Supplier: 無輸入,輸出單個類型
public interface Supplier<T> {
  T get();
}
  • Function: 兩個不同類型的輸入
public interface Function<T, R> {
  R apply(T t); // 輸入T類型,轉(zhuǎn)換成R類型
}
  • ToIntFunction / ToLongFunction / ToDoubleFunction
public interface ToIntFunction<T> {
    // T類型的輸入,輸出int 
    // 類似于Stream的mapToInt()
    int applyAsInt(T value); 
}
  • IntFunction / LongFunction / DoubleFunction
public interface IntFunction<R> {
    R apply(int value);
}
  • BiFunction: 兩個不同類型的輸入永丝,第三種類型的輸出
public interface BiFunction<T, U, R> {
  R apply(T t, U u);
}
  • 條件測試
public interface Predicate<T> {
  boolean test(T t);
}

可以不用自定義函數(shù)式接口來支持lambda锹漱,上面的例子可以改成:

public void printWithFilter(List<HouseInfo> houseList, Predicate<HouseInfo> condition) {
  houseList.stream().filter(e -> condition.test(e)).forEach(System.out::println);
}

關(guān)于lambda的傳說和他到底是什么鬼,看到這里應(yīng)該夠了慕嚷。

畢竟我們的主要目的是使用它哥牍,知道他怎么用才是重點。

沒必要糾結(jié)他嚴(yán)格的學(xué)術(shù)定義(這種事不應(yīng)該是那種只會紙上談兵的老不死干的嗎喝检?)嗅辣。

在Java8里和lambda相關(guān)的主要API就是Stream了。在了解Stream的時候來順便熟悉lambda吧挠说。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末澡谭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子损俭,更是在濱河造成了極大的恐慌蛙奖,老刑警劉巖潘酗,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異雁仲,居然都是意外死亡崎脉,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進(jìn)店門伯顶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來囚灼,“玉大人,你說我怎么就攤上這事祭衩≡钐澹” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵掐暮,是天一觀的道長蝎抽。 經(jīng)常有香客問我,道長路克,這世上最難降的妖魔是什么樟结? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮精算,結(jié)果婚禮上瓢宦,老公的妹妹穿的比我還像新娘。我一直安慰自己灰羽,他們只是感情好驮履,可當(dāng)我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著廉嚼,像睡著了一般玫镐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上怠噪,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天恐似,我揣著相機(jī)與錄音,去河邊找鬼傍念。 笑死矫夷,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的捂寿。 我是一名探鬼主播口四,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼秦陋!你這毒婦竟也來了蔓彩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赤嚼,沒想到半個月后旷赖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡更卒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年等孵,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蹂空。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡俯萌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出上枕,到底是詐尸還是另有隱情咐熙,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布辨萍,位于F島的核電站棋恼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏锈玉。R本人自食惡果不足惜爪飘,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拉背。 院中可真熱鬧师崎,春花似錦、人聲如沸去团。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽土陪。三九已至,卻和暖如春肴熏,著一層夾襖步出監(jiān)牢的瞬間鬼雀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工蛙吏, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留源哩,地道東北人。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓鸦做,卻偏偏與公主長得像励烦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子泼诱,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,452評論 2 348

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

  • 前言 人生苦多坛掠,快來 Kotlin ,快速學(xué)習(xí)Kotlin! 什么是Kotlin屉栓? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,161評論 9 118
  • lambda表達(dá)式(又被成為“閉包”或“匿名方法”)方法引用和構(gòu)造方法引用擴(kuò)展的目標(biāo)類型和類型推導(dǎo)接口中的默認(rèn)方法...
    183207efd207閱讀 1,473評論 0 5
  • Java8 in action 沒有共享的可變數(shù)據(jù)舷蒲,將方法和函數(shù)即代碼傳遞給其他方法的能力就是我們平常所說的函數(shù)式...
    鐵牛很鐵閱讀 1,220評論 1 2
  • 在C++11中,我們還是會看到一些新元素友多。這些新鮮出爐的元素可能會帶來一些習(xí)慣上的改變,不過權(quán)衡之下,可能這樣的改...
    認(rèn)真學(xué)計算機(jī)閱讀 5,469評論 1 27
  • 簡介 概念 Lambda 表達(dá)式可以理解為簡潔地表示可傳遞的匿名函數(shù)的一種方式:它沒有名稱自沧,但它有參數(shù)列表序矩、函數(shù)主...
    劉滌生閱讀 3,194評論 5 18