1. 程式人生 > >Java8新特性——Lambda表示式(一)

Java8新特性——Lambda表示式(一)

這裡寫圖片描述

1. 預備知識

在瞭解Lambda表示式之前首先需要了解以下預備知識。

1.1 如何成為一名高階碼農?

如果老闆讓你寫一個用於毀滅地球的函式,而你寫了一個毀滅行星的函式,若要毀滅地球只需將毀滅地球的過程傳遞給“毀滅行星”。能做到這一點,你就是一名高階碼農。

以上這個問題體現了程式可擴充套件性的思想。總結一下,要成為一名高階碼農,在編碼的時候要以發展的眼光看待問題。一個具體問題到來的時候,你需要基於當前問題抽象出解決這一類問題的辦法,那麼當相似的問題到來時,你只需花少量的時間就能完成任務,而且避免了程式碼複製,降低了bug的風險。

1.2 實現程式可擴充套件性的例子

在Java8以前,要實現程式的可擴充套件性,我們常用匿名內部類傳遞用於擴充套件的程式碼,舉個例子:

實現一個能從List集合中篩選指定物件的函式filter。
1. 若List中存放Person物件,要求篩選出30歲以上的Person
2. 若List中存放Apple,要求篩選出紅色的Apple

使用匿名內部類的解決方案:

  • 實現filter函式
List<T> filter(List<T> list, FilterProcessor filterProcessor){
    List<T> result = new ArrayList<T>();
    for(T t : list){
        if
(filterProcessor.process(t)) result.add(t); } return list; }
  • 定義FilterProcessor介面
interface FilterProcessor<T>{
    boolean process(T);
}
  • 使用匿名內部類實現篩選出30歲以上的Person
List<Person> result = filter(list, new FilterProcessor<Person>(){
    boolean process(Person person){
        if
(person.getAge()>=30) return true; return false; } });
  • 使用匿名內部類篩選出紅色的Apple
List<Apple> result = filter(list, new FilterProcessor<Apple>(){
    boolean process(Apple apple){
        if(apple.getColor().equals("red"))
            return true;
        return false;
    }
});

若要增加新的篩選規則,只需給filter函式傳遞新的匿名內部類即可。程式具有了可擴充套件性,恭喜你已經成為一名高階碼農!

1.3 什麼是“策略模式”?

上述過程總結來說,當我們需要解決同一類問題的時候,若發現這類問題大部分處理過程是一致的,只是核心步驟存在差異,這時候就可以使用上述方式:先把函式相同的部分寫好,再抽象出一個介面,不同部分的程式碼放在介面的實現類中。要使用時,只需將實現類的物件傳遞給該函式即可。
這種方式在設計模式中稱為“策略模式”。

1.4 使用匿名內部類實現策略模式的弊端?

使用匿名內部類實現策略模式程式碼比較冗餘,不易閱讀,就像這樣:

List<Apple> result = filter(list, new FilterProcessor<Apple>(){
    boolean process(Apple apple){
        if(apple.getColor().equals("red"))
            return true;
        return false;
    }
});

Java8提出了Lambda表示式,它是實現策略模式的另外一種方式,目的就是為了使程式碼簡單清晰。
使用Lambda表示式實現相同功能:

List<Apple> result = filter(list, (Apple apple)—>apple.getColor().equals("red"));

這樣是不是簡單多了!Lambda表示式本質上是將一個函式的程式碼作為一個引數或變數進行傳遞,這種處理方式有個專門的名字——函數語言程式設計。

1.5 什麼是函數語言程式設計?

所謂“函式式”程式設計,就是將函式的程式碼當作一個變數,傳遞給另一個變數或傳遞給一個函式,這種程式設計方式就稱為“函數語言程式設計”。
Java8中採用Lambda表示式實現函數語言程式設計,它是策略模式的第二種實現方式,目的就是簡化策略模式的程式碼實現。

2. Lambda表示式的語法

Lambda表示式用於表示一個函式,所以它和函式一樣,也擁有引數、返回值、函式體,但它沒有函式名,所以Lambda表示式相當於一個匿名函式。語法如下:

(Person person)—>person.getAge()>30

Lambda表示式用—>連線,->左側為函式的引數,->右側為函式體。
若右側由多條語句構成則需要用{}包裹,如:

(Person person)—>{person.getAge()>30;System.out.println(person.getName());}

Lambda表示式無需顯示指定返回值型別,JVM會根據->右側語句的返回結果自動判斷返回值型別,如:

(Person person)—>person.getAge()>30 #自動判斷返回值為boolean型

3. 如何使用Lambda表示式?

仍以篩選年齡大於30的Person物件為例:

3.1 為Lambda表示式定義函式式介面

@FunctionalInterface
interface FilterProcessor<T>{
    boolean process(T t);
}

PS:該介面只能有一個抽象函式!接下來Lambda表示式就是該抽象函式的實現。
PS:在為Lambda表示式定義函式式介面時,需要加上註解@FunctionalInterface,這樣當該介面中抽象函式個數不是1時就會報錯提示。

3.2 實現篩選函式

List<T> filter(List<T> list, FilterProcessor<T> filterProcessor){
    List<T> result = new ArrayList<T>();
    if(filterProcessor.process(t))
        result.add(t);
    return result;
}

filter函式接收一個函式式介面,該引數用於接收一個Lambda表示式。

3.3 傳遞Lambda表示式

List<Person> result = filter(list, (Person p)->p.getAge()>30);

直接將Lambda表示式作為引數傳遞給filter的函式式介面即可,從而在result中就能獲取年齡超過30歲的Person物件。

這裡寫圖片描述