1. 程式人生 > >死磕Lambda表示式(一):初識Lambda

死磕Lambda表示式(一):初識Lambda

弱小和無知不是生存的障礙,傲慢才是。——《三體》

什麼是Lambda表示式

Lambda表示式是表示可傳遞匿名函式的一種簡潔方式,Lambda表示式沒有名稱,但是有引數列表、函式主體、返回型別,還可能有一個可以丟擲的異常列表。它是Java8新增的特性,有了它我們再也不用像之前那樣寫一堆笨重的匿名類程式碼了,我們先來體驗一下。

歡迎關注微信公眾號:萬貓學社,每週一分享Java技術乾貨。

與匿名函式對比

下面我們先舉個例子,有這樣一個表示口罩的類:

package one.more.study;

/**
 * 口罩
 */
public class Mask {
    /**
     * 品牌
     */
    private String brand;
    /**
     * 型別
     */
    private String type;

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}

再建立一個口罩列表,新增一些口罩物件:

List<Mask> maskList = new ArrayList<>();
maskList.add(new Mask("3M", "KN95"));
maskList.add(new Mask("3M", "FFP2"));
maskList.add(new Mask("Honeywell", "KN95"));
maskList.add(new Mask("Honeywell", "N95"));

現在我們按照品牌給這個口罩列表進行排序。在Java8之前,我們可以用匿名函式進行實現:

maskList.sort(new Comparator<Mask>() {
    @Override
    public int compare(Mask o1, Mask o2) {
        return o1.getBrand().compareTo(o2.getBrand());
    }
});

我們再使用Lambda表示式實現一下:

maskList.sort((Mask o1, Mask o2) -> o1.getBrand().compareTo(o2.getBrand()));

顯而易見,使用Lambda表示式以後,程式碼看起來更清晰更簡潔了。假如你還是一臉懵圈的話也沒關係,這裡我只是想顯擺一下Lambda表示式很牛掰,接下來我會一點點地詳細講解清楚。

歡迎關注微信公眾號:萬貓學社,每週一分享Java技術乾貨。

Lambda表示式的組成

Lambda表示式由三部分組成,以上面的口罩排序的例子為例,如下圖:

  1. 引數列表:本例中是兩個Mask物件的引數,採用的是Comparator介面中compare方法的引數。
  2. 箭頭:->把引數列表和主體分隔為兩個部分。
  3. 主體:本例中是把比較口罩品牌的表示式作為Lambda表示式的返回。主體可以修改成另外一種寫法,含義是一樣的:
maskList.sort((Mask o1, Mask o2) -> {
    return o1.getBrand().compareTo(o2.getBrand());
});

歡迎關注微信公眾號:萬貓學社,每週一分享Java技術乾貨。

Lambda表示式的基本語法

從上面的例子中的兩個種寫法中,可以看出Lambda表示式有兩種基本語法,分別如下:

  1. (引數列表) -> 表示式
  2. (引數列表) -> { 多條語句 }

只看這兩條幹癟的語法,理解起來比較困難,實踐出真知,我們來多舉幾個例子。

歡迎關注微信公眾號:萬貓學社,每週一分享Java技術乾貨。

Lambda表示式示例

  1. 我們提到的例子,Lambda表示式的引數列表有兩個Mask型別的引數,主體是比較兩個Mask物件的品牌,返回的是一個int型別。當主體是一個表示式時,不需要return語句,隱含return該表示式的返回值。
(Mask o1, Mask o2) -> o1.getBrand().compareTo(o2.getBrand())
  1. 引數列表中僅有一個Mask型別的引數,返回的是一個String型別,是該Mask物件的品牌資訊。
(Mask mask) -> mask.getBrand()
  1. 引數列表中僅有一個Mask型別的引數,返回的是一個boolean型別,是該Mask物件的型別是否為N95。
(Mask mask) -> mask.getType() == "N95"
  1. 引數列表中沒有任何引數,返回的是一個int型別。
() -> 996
  1. 引數列表中有兩個int型別的引數,但是沒有返回值(void)。在主體中可以寫多條語句,不過記住要用{}將其包裹。
(int x, int y) -> {
    System.out.println("萬貓學社想對你說:");
    System.out.println("第一個引數是:" + x);
    System.out.println("第二個引數是:" + y);
    System.out.println("兩數之和是:" + (x + y));
}

歡迎關注微信公眾號:萬貓學社,每週一分享Java技術乾貨。

小測試

看了這麼多的例子,是不是擼胳膊挽袖子準備大幹一場?別急,檢驗出真知,我們先簡單測試一下。以下的Lambda表示式有哪幾個是正確的?

  1. () -> {}
  2. () -> "萬貓學社"
  3. () -> { "萬貓學社" }
  4. () -> { return "萬貓學社"; }
  5. () -> return "萬貓學社";

請思考片刻…
.
.
.

.
.
.

歡迎關注微信公眾號:萬貓學社,每週一分享Java技術乾貨。

宣佈答案:第1、2和4個是正確的,第3和5個是錯誤的。我們來逐個分析一下:

  1. () -> {}:正確,這個Lambda表示式沒有引數,也沒有任何返回。
  2. () -> "萬貓學社":正確,這個Lambda表示式沒有引數,主體是一個表示式,返回String型別。
  3. () -> { "萬貓學社" }:錯誤,"萬貓學社"是一個表示式,不是一個語句,不能使用{}將其包裹,可以修改為() -> "萬貓學社"
  4. () -> { return "萬貓學社"; }:正確,這個Lambda表示式沒有引數,主體是一個語句,使用{}將其包裹,返回String型別。
  5. () -> return "萬貓學社";:錯誤,return "萬貓學社";是一個語句,不是一個表示式,必須使用{}將其包裹,可以修改為() -> { return "萬貓學社"; }

如果你全部答對,恭喜你,你已經基本掌握Lambda表示式的基本語法;如果你有答錯的,沒關係,重新再看一遍,再複習鞏固一下。
學習的路上,我與你一起前行。

歡迎關注微信公眾號:萬貓學社,每週一分享Java技術乾貨