Java8 中的Lambda表達式

對于一個新事物拒啰,我們應該從這三方面來認識驯绎,是什么完慧?為什么會出現(xiàn)谋旦?怎么用?

一屈尼、Lambda表達式是什么?

它是Java8的一個新特性册着,正如學習一門新語言要先自己手寫一個HelloWorld一樣,我們先寫一個Lambda表達式的HelloWorld脾歧。比如遍歷輸出一個List:

        List<String> list = new ArrayList<String>();
        list.add("renheng");
        list.add("fangmiao");
        //java8以前遍歷集合
        for(String str : list){
            System.out.println(str);
        }
        //使用Lamada表達式遍歷集合
        list.stream().forEach(str -> System.out.println(str));

1.Lambda表達式的形式化表示如下所示

Parameters -> an expression 

2.如果Lambda表達式中要執(zhí)行多個語句塊,需要將多個語句塊以{}進行包裝甲捏,如果有返回值,需要顯示指定return語句鞭执,如下所示:

Parameters -> {expressions;};

3.如果Lambda表達式不需要參數(shù)司顿,可以使用一個空括號表示芒粹,如下示例所示

() -> {for (int i = 0; i < 1000; i++) doSomething();};

二、Lambda表達式有哪些方便之處大溜?
lambda表達式化漆,它將允許我們將行為傳到函數(shù)里。在Java 8之前钦奋,如果想將行為傳入函數(shù)座云,僅有的選擇就是匿名類,需要6行代碼付材。而定義行為最重要的那行代碼朦拖,卻混在中間不夠突出。Lambda表達式取代了匿名類厌衔,取消了模板璧帝,允許用函數(shù)式風格編寫代碼。這樣有時可讀性更好葵诈,表達更清晰裸弦。在Java生態(tài)系統(tǒng)中,函數(shù)式表達與對面向對象的全面支持是個激動人心的進步作喘。將進一步促進并行第三方庫的發(fā)展理疙,充分利用多核CPU。我認為任何嚴謹?shù)腏ava開發(fā)者都不應忽視此次Java發(fā)布的核心特性泞坦,即lambda表達式窖贤、函數(shù)式接口、流API贰锁、默認方法和新的Date以及Time API赃梧。作為開發(fā)人員,我發(fā)現(xiàn)學習和掌握lambda表達式的最佳方法就是勇于嘗試豌熄,盡可能多練習lambda表達式例子授嘀。鑒于受Java 8發(fā)布的影響最大的是Java集合框架(Java Collections framework),所以最好練習流API和lambda表達式锣险,用于對列表(Lists)和集合(Collections)數(shù)據(jù)進行提取蹄皱、過濾和排序。下面是Lambda表達式的幾個應用芯肤。
三巷折、怎么使用Lambda表達式?
1.使用Lambda表達式代替匿名內部類:
那就是用() -> {}代碼塊替代了整個匿名類:
比如給一個按鈕添加監(jiān)聽事件崖咨,當點擊時在控制臺打印一行字符串锻拘。

        Button button = new Button("點擊");
        //java8以前
        button.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent arg0) {
                System.out.println("點擊了我一下");
            }
            
        });
        //java8
        button.addActionListener((e) -> System.out.println("點擊了我一下"));

再比如想對一個Integer列表進行降序排序輸出:

            List<Integer> list = Lists.newArrayList(1,2,9,5,10,11);
            //java8以前
            Collections.sort(list, new Comparator(){
                @Override
                public int compare(Object ob1, Object ob2) {
                    Integer a = (Integer)ob1;
                    Integer b = (Integer)ob2;
                    return b - a;
                }
            });
            //java8
            Collections.sort(list, (a,b) -> b-a);

Collectons的sort方法默認是按升序排列,如果要按降序排列击蹲,需要重寫Comparator接口的compare方法署拟。發(fā)現(xiàn)使用Lambda表達式一行代碼就搞定婉宰!
2.流Stream
2.1 filter():對流過濾
任務:創(chuàng)建一個姓氏集合,要求出所有初始字母為L的人的總數(shù)目推穷。使用流處理的代碼如下:

            List<String> list = Lists.newArrayList("Ren","Liu","Li","Lu");
            Long count = list.stream().filter(a -> a.startsWith("L")).count();
            System.out.println("以L開頭的姓氏有" + count + "個");

2.2 map():將集合類(例如列表)元素進行轉換
任務:對工資表中超過3500的部分征收20%的稅芍阎,得到稅后的工資表。
使用流處理的代碼如下:

            List<Double> salaryBeforeTax = Lists.newArrayList(4000.0,5500.0,6000.0,7000.0);
            List<Double> salaryAfterTax = salaryBeforeTax.stream().map(a -> a - (a-3500)*0.2).collect(Collectors.toList());

map方法對流中的每一個對象進行繳稅操作缨恒,得到稅后的工資谴咸,然后使用collect方法將這些新值轉換成一個新的list。其中Collectors有toList方法骗露,還有toSet岭佳、toMap方法等,看你想得到什么類型的集合了萧锉。
任務:將姓氏列表中的值全部轉換成大寫字母

         List<String> list = Lists.newArrayList("Ren","Liu","Li","Lu");
         List<String> upperList = list.stream().map(a -> a.toUpperCase()).collect(Collectors.toList());

2.3 reduce: reduce() 函數(shù)可以將所有值合并成一個,又被稱為折疊操作,SQL中類似 sum()珊随、avg() 或者 count() 的聚集函數(shù),實際上就是 reduce 操作柿隙,因為它們接收多個值并返回一個值叶洞。
任務:對工資表超過3500的部分進行扣稅(20%),并將稅后的值進行相加計算總和禀崖。

List<Double> salaryBeforeTax = Lists.newArrayList(4000.0,5500.0,6000.0,7000.0);
Double sum =  salaryBeforeTax.stream().map(a -> a-(a-3500)*0.2).reduce((s,b) -> s+b).get();
System.out.println(sum);

//1.無初始值累加
T t = salaryBeforeTax.stream().reduce((a,b)->a+b);
//2.帶初始值累加
Optional<T> t = salaryBeforeTax.stream().reduce("1",(a,b)->a+b);

2.4對列表的每個元素應用函數(shù)
我們通常需要對列表的每個元素使用某個函數(shù)衩辟,例如逐一乘以某個數(shù)、除以某個數(shù)或者做其它操作波附。這些操作都很適合用 map() 方法艺晴,可以將轉換邏輯以lambda表達式的形式放在 map() 方法里,就可以對集合的各個元素進行轉換了掸屡,如下所示封寞。

// 將字符串換成大寫并用逗號鏈接起來
List<String> G7 = Arrays.asList("USA", "Japan", "France", "Germany", "Italy", "U.K.","Canada");
String G7Countries = G7.stream().map(x -> x.toUpperCase()).collect(Collectors.joining(", "));
System.out.println(G7Countries);
輸出:USA, JAPAN, FRANCE, GERMANY, ITALY, U.K., CANADA

2.5利用流的 distinct() 方法來對集合進行去重。

// 用所有不同的數(shù)字創(chuàng)建一個正方形列表
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());
輸出:81, 100, 9, 16, 49

2.6計算集合元素的最大值仅财、最小值狈究、總和以及平均值
IntStream、LongStream 和 DoubleStream 等流的類中盏求,有個非常有用的方法叫做 summaryStatistics() 抖锥。可以返回 IntSummaryStatistics风喇、LongSummaryStatistics 或者 DoubleSummaryStatistic s宁改,描述流中元素的各種摘要數(shù)據(jù)缕探。在本例中魂莫,我們用這個方法來計算列表的最大值和最小值。它也有 getSum() 和 getAverage() 方法來獲得列表的所有元素的總和及平均值爹耗。

List<Double> salaryBeforeTax = Lists.newArrayList(4000.0,5500.0,6000.0,7000.0);
DoubleSummaryStatistics  summary =  salaryBeforeTax.stream().mapToDouble(a -> a).summaryStatistics();
System.out.println("最高工資:" + summary.getMax());
System.out.println("最低工資:" + summary.getMin());
System.out.println("平均工資:" + summary.getAverage());
System.out.println("工資總計:" + summary.getSum());
輸出:
最高工資:7000.0
最低工資:4000.0
平均工資:5625.0
工資總計:22500.0

2.7 flatMap:把多個流合并為一個流

List<Integer> list1 = Lists.newArrayList(1,2,3);
List<Integer> list2 = Lists.newArrayList(4,5,6);
List<Integer> all = Stream.of(list1,list2).flatMap(a -> a.stream()).collect(Collectors.toList());
for(Integer n:all){
     System.out.print(n);
}
輸出:123456
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末耙考,一起剝皮案震驚了整個濱河市谜喊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌倦始,老刑警劉巖斗遏,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鞋邑,居然都是意外死亡诵次,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門枚碗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逾一,“玉大人,你說我怎么就攤上這事肮雨∽穸拢” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵怨规,是天一觀的道長陌宿。 經(jīng)常有香客問我,道長波丰,這世上最難降的妖魔是什么壳坪? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮掰烟,結果婚禮上弥虐,老公的妹妹穿的比我還像新娘。我一直安慰自己媚赖,他們只是感情好霜瘪,可當我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著惧磺,像睡著了一般颖对。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上磨隘,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天缤底,我揣著相機與錄音,去河邊找鬼番捂。 笑死个唧,一個胖子當著我的面吹牛,可吹牛的內容都是我干的设预。 我是一名探鬼主播徙歼,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了魄梯?” 一聲冷哼從身側響起桨螺,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎酿秸,沒想到半個月后灭翔,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡辣苏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年肝箱,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稀蟋。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡狭园,死狀恐怖,靈堂內的尸體忽然破棺而出糊治,到底是詐尸還是另有隱情唱矛,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布井辜,位于F島的核電站绎谦,受9級特大地震影響,放射性物質發(fā)生泄漏粥脚。R本人自食惡果不足惜窃肠,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望刷允。 院中可真熱鬧冤留,春花似錦、人聲如沸树灶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽天通。三九已至泊窘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間像寒,已是汗流浹背烘豹。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留诺祸,地道東北人携悯。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像筷笨,于是被迫代替她去往敵國和親憔鬼。 傳聞我的和親對象是個殘疾皇子龟劲,可洞房花燭夜當晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內容

  • Java 8 lambda表達式示例 轉自importNew 原文鏈接 例1、用lambda表達式實現(xiàn)Runnab...
    低至一折起閱讀 1,371評論 0 3
  • Java8 in action 沒有共享的可變數(shù)據(jù)逊彭,將方法和函數(shù)即代碼傳遞給其他方法的能力就是我們平常所說的函數(shù)式...
    鐵牛很鐵閱讀 1,235評論 1 2
  • 聲明:本文翻譯自The Java? Tutorials(官方文檔) 簡述 匿名類有一個問題,如果匿名類的實現(xiàn)非常簡...
    猴子小皮球閱讀 4,668評論 0 9
  • 想做的事常被現(xiàn)實束縛构订, 想直言的話又習慣隱忍侮叮, 喜歡的人總是錯過, 我們的人生啊悼瘾, 仔細檢查一遍又一遍囊榜, 交了答卷...
    火星之旅閱讀 349評論 0 6
  • 今天朱妍起的不算早,不亥宿,應該是很遲卸勺。 她隱約記得昨天晚上起夜的時候,走廊外咯噔咯噔的高跟鞋聲烫扼。她迷迷糊糊地看了看手...
    唐小茴閱讀 328評論 1 0