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

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

什麼是Lambda表達式

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

與匿名函數對比

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

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表達式很牛掰,接下來我會一點點地詳細講解清楚。

Lambda表達式的組成

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

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

Lambda表達式的基本語法

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

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

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

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));
}

小測試

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

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

請思考片刻…
.
.
.

.
.
.

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

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

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

《死磕Lambda表達式》目錄

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章