JDK1.8 之Lambda表示式

不甘於平凡的潰敗發表於2019-04-02

更多精彩技術分享請瀏覽本人部落格:https://blog.csdn.net/wohiusdashi

 

概述

Lambda 表示式是一種匿名函式(對 Java 而言這並不完全正確,但現在姑且這麼認為),簡單地說,它是沒有宣告的方法,也即沒有訪問修飾符、返回值宣告和名字。

你可以將其想做一種速記,在你需要使用某個方法的地方寫上它。當某個方法只使用一次,而且定義很簡短,使用這種速記替代之尤其有效,這樣,你就不必在類中費力寫宣告與方法了。
 

Lambda 表示式的結構

  • 一個 Lambda 表示式可以有零個或多個引數
  • 引數的型別既可以明確宣告,也可以根據上下文來推斷。例如:(int a)與(a)效果相同
  • 所有引數需包含在圓括號內,引數之間用逗號相隔。例如:(a, b) 或 (int a, int b) 或 (String a, int b, float c)
  • 空圓括號代表引數集為空。例如:() -> 42
  • 當只有一個引數,且其型別可推導時,圓括號()可省略。例如:a -> return a*a
  • Lambda 表示式的主體可包含零條或多條語句
  • 如果 Lambda 表示式的主體只有一條語句,花括號{}可省略。匿名函式的返回型別與該主體表示式一致
  • 如果 Lambda 表示式的主體包含一條以上語句,則表示式必須包含在花括號{}中(形成程式碼塊)。匿名函式的返回型別與程式碼塊的返回型別一致,若沒有返回則為空

什麼是函式式介面


在 Java 中,Marker(標記)型別的介面是一種沒有方法或屬性宣告的介面,簡單地說,marker 介面是空介面。相似地,函式式介面是隻包含一個抽象方法宣告的介面。

語法

parameter -> expression body

下面是一個lambda表示式的重要特徵。

  • 可選型別宣告 - 無需宣告引數的型別。編譯器可以從該引數的值推斷。

  • 可選圓括號引數 - 無需在括號中宣告引數。對於多個引數,括號是必需的。

  • 可選大括號 - 表示式主體沒有必要使用大括號,如果主體中含有一個單獨的語句。

  • 可選return關鍵字 - 編譯器會自動返回值,如果主體有一個表示式返回的值。花括號是必需的,以表明表示式返回一個值。

變數作用域:

  在lambda表示式,可以指任何最終的變數或有效的最後一個變數(被分配一次)。如果變數被二次賦值,lambda表示式將丟擲編譯錯誤。

小牛試刀

實踐是檢驗真理的唯一標準,哈哈,請看

 new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("我是傳統的寫法");
            }
        }).start();
//------------------------------------------------------------
new Thread(() -> System.out.println("我是Lambda的寫法")).start();

輸出結果:

從以上程式碼可以看出使用Lambda表示式的好處就是節省程式碼量,因為使用Lambda表示式只需要一行程式碼可以搞定的事情使用傳統寫法需要6行程式碼。

如果您認為Lambda表示式只是用來簡化程式碼量的話,那您就大錯特錯了,哈哈,下面請看Lambda表示式更高階用法

1、 forEach遍歷輸出

奉上程式碼:

 List<String> list = new ArrayList<String>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        System.out.println("傳統遍歷輸出方式");
        for(String str : list){
            System.out.println(str);
        }
        System.out.println("Lambda表達遍歷輸出方式");
        list.forEach(System.out::println);

輸出結果:

2、條件過濾

奉上程式碼:

 List<Integer> list = new ArrayList<Integer>();
        for(int i = 0 ;i < 100; i++)
            list.add(i);
        //過濾小於90的數字
        List<Integer> newList = list.stream().filter(a -> a >90).collect(Collectors.toList());
        newList.forEach(System.out::println);

輸出結果:

3、批量增、減操作

奉上程式碼:

        List<Double> list = Arrays.asList(3000.0,5000.0,8000.0,10000.0,20000.0,50000.0);
        //大BOSS發話,從現在開始每個程式設計師漲薪 30%
        System.out.println("------------傳統寫法");
        for(Double salary :  list){
            System.out.println(salary * 1.3);
        }
        System.out.println("------------Lambda 表示式寫法");
        list.stream().map(a -> a*1.3).forEach(System.out::println);

輸出結果:

4、求最大值、最小值、平均值

奉上程式碼:

List<Integer> list = new ArrayList<Integer>();
        for(int i = 0 ;i < 100; i++)
            list.add(i);
        IntSummaryStatistics iss =list.stream().mapToInt((x) -> x).summaryStatistics();
        System.out.println("最大值: "+iss.getMax());
        System.out.println("最小值: "+iss.getMin());
        System.out.println("平均值: "+iss.getAverage());

輸出結果:

 

一不留神看了下時間,現在都晚上12點了,也該睡覺了,還有關於 @FunctionalInterface、中間操作、終值操作 等其它內容 只能下次再進行講解,感興趣的朋友可以關注我,哈哈。

 

更多精彩技術分享請瀏覽本人部落格:https://blog.csdn.net/wohiusdashi

 

相關文章