Java lambda表達(dá)式

lambda表達(dá)式是Java 8 中的一個(gè)很重要的新特性,它容許將行為傳到函數(shù)中。在Java 8 之前贪磺,如果我們想要把行為傳到函數(shù)中,僅有的選擇就是匿名內(nèi)部類(lèi)诅愚。但Java 8 發(fā)布以后寒锚,lambda表達(dá)式將大量替代匿名內(nèi)部類(lèi)的使用,簡(jiǎn)化代碼违孝,突出匿名內(nèi)部類(lèi)中最重要的邏輯代碼刹前。下面以Runable接口說(shuō)明這一點(diǎn):

Runnable runnable = new Runnable() {
      @Override
      public void run() {
        System.out.println(Thread.currentThread().getName());
      }
    };

使用lambda表達(dá)式簡(jiǎn)化:

Runnable runnable1 = () -> System.out.println(Thread.currentThread().getName());

一、lambda表達(dá)式簡(jiǎn)介

lambda表達(dá)式是一個(gè)匿名函數(shù)等浊,一種沒(méi)有聲明的方法腮郊,沒(méi)有修飾符,返回值聲明和名稱(chēng)筹燕。Java中的lambda表達(dá)式通常使用語(yǔ)法是(parameters) -> (expression)(parameters) ->{ statements; },例如:

// 接收兩個(gè)int型參數(shù)轧飞,返回它們的值
(int a, int b) -> {  return a + b; }
// 無(wú)參數(shù)
() -> System.out.println("Hello World");
// 接收一個(gè)String型字符串衅鹿,打印字符串
(String s) -> { System.out.println(s); }
// 無(wú)參數(shù) 返回 42
() -> 42
// 無(wú)參數(shù),返回3.1415
() -> { return 3.1415 };

lambda表達(dá)式的結(jié)構(gòu)說(shuō)明:

  • Lambda 表達(dá)式可以具有零個(gè)过咬,一個(gè)或多個(gè)參數(shù)大渤;
  • 可以顯式聲明參數(shù)的類(lèi)型,也可以由編譯器自動(dòng)從上下文推斷參數(shù)的類(lèi)型掸绞。例如 (int a) 與剛才相同 (a)泵三;
  • 參數(shù)用小括號(hào)括起來(lái),用逗號(hào)分隔衔掸。例如 (a, b) 或 (int a, int b) 或 (String a, int b, float c)烫幕;
  • 空括號(hào)用于表示一組空的參數(shù)。例如 () -> 42敞映;
  • 當(dāng)有且僅有一個(gè)參數(shù)時(shí)较曼,如果不顯式指明類(lèi)型,則不必使用小括號(hào)振愿。例如 a -> return a*a捷犹;
  • Lambda 表達(dá)式的正文可以包含零條,一條或多條語(yǔ)句冕末;
  • 如果 Lambda 表達(dá)式的正文只有一條語(yǔ)句萍歉,則大括號(hào)可不用寫(xiě),且表達(dá)式的返回值類(lèi)型要與匿名函數(shù)的返回類(lèi)型相同档桃;
  • 如果 Lambda 表達(dá)式的正文有一條以上的語(yǔ)句必須包含在大括號(hào)(代碼塊)中枪孩,且表達(dá)式的返回值類(lèi)型要與匿名函數(shù)的返回類(lèi)型相同。

二胳蛮、lambda表達(dá)式示例

1. 使用Java 8 lambda表達(dá)式進(jìn)行事件處理

java 8 之前:

JButton show =  new JButton("Show");
    show.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        System.out.println("Hello world");
      }
    });

java 8 :

show.addActionListener((e) -> {
    System.out.println("Hello world");
});
2. 使用Java 8 lambda表達(dá)式進(jìn)行列表迭代

java 8 之前:

List<String> items = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
for (String item : items) {
  System.out.println(item);
}

java 8 :

items.forEach(item -> System.out.println(item));

java 8 之前:

Map<String,String> map = new HashMap <>();
map.put("1","a");
map.put("2","b");
map.put("3","c");
for(String key : map.keySet()){
  System.out.println(map.get(key));
}

java 8 :

map.forEach((k,v)->System.out.println(map.get(k)));
3. 使用lambda表達(dá)式和函數(shù)式接口Predicate進(jìn)行邏輯操作

Java 8 添加了一個(gè) java.util.function 的包销凑。它包含了很多類(lèi)丛晌,用來(lái)支持Java的函數(shù)式編程仅炊。其中一個(gè)便是Predicate,使用 java.util.function.Predicate 函數(shù)式接口以及l(fā)ambda表達(dá)式澎蛛,可以向API方法添加邏輯抚垄,用更少的代碼支持更多的動(dòng)態(tài)行為。

public static void main(String[] arg){
    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);

    System.out.print("輸出所有數(shù)字:");
    evaluate(list, (n) -> true);

    System.out.print("不輸出:");
    evaluate(list, (n) -> false);

    System.out.print("輸出偶數(shù):");
    evaluate(list, (n) -> n % 2 == 0);

    System.out.print("輸出奇數(shù):");
    evaluate(list, (n) -> n % 2 == 1);

    System.out.print("輸出大于 5 的數(shù)字:");
    evaluate(list, (n) -> n > 5);
  }
  public static void evaluate(List<Integer> list, Predicate<Integer> predicate) {
//    for (Integer n : list) {
//      if (predicate.test(n)) {
//        System.out.print(n + " ");
//      }
//    }
    list.stream().filter(name -> predicate.test(name)).forEach(name -> System.out.println(name+" "));
  }
4. 多個(gè)Predicate合并使用

java.util.function.Predicate允許將兩個(gè)或更多的 Predicate 合成一個(gè)谋逻。它提供類(lèi)似于邏輯操作符AND和OR的方法呆馁,名字叫做and()、or()和xor()毁兆,用于將傳入 filter() 方法的條件合并起來(lái)浙滤。例如,要得到所有以J開(kāi)始气堕,長(zhǎng)度為四個(gè)字母的語(yǔ)言纺腊,可以定義兩個(gè)獨(dú)立的 Predicate 示例分別表示每一個(gè)條件畔咧,然后用 Predicate.and() 方法將它們合并起來(lái),如下所示:

List<String> list = Arrays.asList("Java", "C", "C++", "Ruby", "C#", "Go");

Predicate<String> startsWithJ = (n) -> n.startsWith("J");
Predicate<String> fourLetterLong = (n) -> n.length() == 4;
list.stream()
        .filter(startsWithJ.and(fourLetterLong))
        .forEach((n) -> System.out.print("nName, which starts with 'J' and four letter long is : " + n));
5. Java 8中使用lambda表達(dá)式的Map和Reduce

java.util.stream.Stream接口 和 Lambda 表達(dá)式一樣揖膜,都是 Java 8 新引入的誓沸。所有 Stream 的操作必須以 Lambda 表達(dá)式為參數(shù)。Stream 接口中帶有大量有用的方法壹粟,比如 map() 的作用就是將 input Stream 的每個(gè)元素映射成output Stream 的另外一個(gè)元素拜隧。

下面的例子,我們將 Lambda 表達(dá)式 x -> x*x 傳遞給map()方法趁仙,將其應(yīng)用于流的所有元素洪添。之后,我們使用forEach打印列表的所有元素:
java 8 之前:

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

java 8 :

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
list.stream().map((x) -> x*x).forEach(System.out::println);

下面的示例中雀费,我們給定一個(gè)列表薇组,然后求列表中每個(gè)元素的平方和。這個(gè)例子中坐儿,我們使用了 reduce() 方法律胀,這個(gè)方法的主要作用是把 Stream 元素組合起來(lái):
java 8 之前:

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
int sum = 0;
for(Integer n : list) {
    int x = n * n;
    sum = sum + x;
}
System.out.println(sum);

java 8 :

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
int sum = list.stream().map(x -> x*x).reduce((x,y) -> x + y).get();
System.out.println(sum);
6. 通過(guò)過(guò)濾創(chuàng)建一個(gè)String列表

過(guò)濾是Java開(kāi)發(fā)者在大規(guī)模集合上的一個(gè)常用操作,而現(xiàn)在使用lambda表達(dá)式和流API過(guò)濾大規(guī)模數(shù)據(jù)集合是驚人的簡(jiǎn)單貌矿。流提供了一個(gè) filter() 方法炭菌,接受一個(gè) Predicate 對(duì)象,即可以傳入一個(gè)lambda表達(dá)式作為過(guò)濾邏輯逛漫。下面的例子是用lambda表達(dá)式過(guò)濾Java集合黑低,將幫助理解。

List<String> strList = Arrays.asList("Java", "C", "C++", "Ruby", "C#", "Go");
// 創(chuàng)建一個(gè)字符串列表酌毡,每個(gè)字符串長(zhǎng)度大于2
List<String> filtered = strList.stream().filter(x -> x.length()> 2).collect(Collectors.toList());
System.out.printf("Original List : %s, filtered list : %s %n", strList, filtered);
7. 去重操作

本例展示了如何利用流的 distinct() 方法來(lái)對(duì)集合進(jìn)行去重:

List<Integer> numbers = Arrays.asList(9, 10, 3, 4, 7, 3, 4);
List<Integer> distinct = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
System.out.printf("Original List : %s,  Square Without duplicates : %s %n", numbers, distinct);
8. 計(jì)算集合元素的最大值克握、最小值、總和以及平均值

IntStream枷踏、LongStream 和 DoubleStream 等流的類(lèi)中菩暗,有個(gè)非常有用的方法叫做 summaryStatistics()⌒袢洌可以返回 IntSummaryStatistics停团、LongSummaryStatistics 或者 DoubleSummaryStatistic s,描述流中元素的各種摘要數(shù)據(jù)掏熬。在本例中佑稠,我們用這個(gè)方法來(lái)計(jì)算列表的最大值和最小值。它也有 getSum() 和 getAverage() 方法來(lái)獲得列表的所有元素的總和及平均值旗芬。

//獲取數(shù)字的個(gè)數(shù)舌胶、最小值、最大值疮丛、總和以及平均值
List<Integer> primes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
IntSummaryStatistics stats = primes.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("Highest prime number in List : " + stats.getMax());
System.out.println("Lowest prime number in List : " + stats.getMin());
System.out.println("Sum of all prime numbers : " + stats.getSum());
System.out.println("Average of all prime numbers : " + stats.getAverage());
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末幔嫂,一起剝皮案震驚了整個(gè)濱河市漱办,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌婉烟,老刑警劉巖娩井,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異似袁,居然都是意外死亡洞辣,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)昙衅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)扬霜,“玉大人,你說(shuō)我怎么就攤上這事而涉≈浚” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵啼县,是天一觀的道長(zhǎng)材原。 經(jīng)常有香客問(wèn)我,道長(zhǎng)季眷,這世上最難降的妖魔是什么余蟹? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮子刮,結(jié)果婚禮上威酒,老公的妹妹穿的比我還像新娘。我一直安慰自己挺峡,他們只是感情好葵孤,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著橱赠,像睡著了一般尤仍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上病线,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天吓著,我揣著相機(jī)與錄音,去河邊找鬼送挑。 笑死,一個(gè)胖子當(dāng)著我的面吹牛暖眼,可吹牛的內(nèi)容都是我干的惕耕。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼诫肠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼司澎!你這毒婦竟也來(lái)了欺缘?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤挤安,失蹤者是張志新(化名)和其女友劉穎谚殊,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蛤铜,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嫩絮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了围肥。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剿干。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖穆刻,靈堂內(nèi)的尸體忽然破棺而出置尔,到底是詐尸還是另有隱情,我是刑警寧澤氢伟,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布榜轿,位于F島的核電站,受9級(jí)特大地震影響朵锣,放射性物質(zhì)發(fā)生泄漏妓笙。R本人自食惡果不足惜肮蛹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧啄枕,春花似錦、人聲如沸煌抒。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)椅您。三九已至外冀,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間掀泳,已是汗流浹背雪隧。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留员舵,地道東北人脑沿。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像马僻,于是被迫代替她去往敵國(guó)和親庄拇。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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