1. 程式人生 > >細說為什麼要使用Lambda表示式

細說為什麼要使用Lambda表示式

Lambda表示式

  • Lambda是一個匿名函式,可以理解為一段可以傳遞的程式碼,將程式碼像資料一樣進行傳遞,可以寫出更加簡介、更加靈活的程式碼。作為一宗更緊湊的程式碼風格,使Java的語言表達能力得到了提升

下面我們使用匿名內部類的方式建立一個執行緒

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        System.out.println("run ... ");
    }
};

Thread thread = new Thread(runnable);
thread
.start();

在上面的程式碼中,我們使用了Runnable介面直接建立了一個物件,用了6行程式碼,但是在這6行程式碼中,真正有用的程式碼只有run方法中的一行

System.out.println("run ... ");

接下來我們使用Lambda表示式來簡化這些程式碼

Runnable runnable = ()-> System.out.println("run ...");
Thread thread = new Thread(runnable);
thread.start();

此時,我們的程式碼就只有三行了,但是這並不是最終的版本,請看下面的程式碼

new
Thread(()->System.out.println("run ... ")).start();

我們使用了最少的程式碼量,實現了同樣的功能

Lambda表示式範例

需求:對教務系統中的學生進行查詢操作

  • 建立一個學生類,屬性分別有姓名,性別,年級
public class Student {
    /**
     * 姓名
     */
    private String name;
    /**
     * 性別
     * 男 1
     * 女 0
     */
    private int gender;
    /**
     * 年級
     * 1 一年級
     * 2 二年級
     * 3 三年級
     * 4 四年級
     */
private int grade; }
  • 需求一:獲取學生中三年級及以上的學生

程式碼思路,將上述的學生集合作為引數,傳入一個過濾的方法中,然後返回符合條件的學生集合

public List<Student> filterStudentsByGrade(List<Student> students){、

    List<Student> stus = new ArrayList<>();
    for (Student s : students){
        if(s.getGrade() >= 3){
            stus.add(s);
        }
    }
    return stus;
}

此時,我們就完美的實現了需求中所要的功能!

但是,日常開發中程式設計師最痛恨的事情發生了,需求改了

  • 需求二:獲取學生中的男同學

思路:最簡單的方式,我們寫一個新的方法

public List<Student> filterStudentsByGender(List<Student> students){
    List<Student> stus = new ArrayList<>();
    for (Student s : students){
        if(s.getGender() == 1){
            stus.add(s);
        }
    }
    return stus;
}

可是,這樣的需求越來越多的時候,我們發現,程式碼中的方法千篇一律,每個方法中只有判斷的條件不一樣,其他的程式碼都是一樣的,大量的冗餘程式碼,要求我們必須要對程式碼進行優化、重構

無數的前輩們在趟過了無數的坑之後,為我們總結出來了非常好的優化程式碼的東西————設計模式

接下來,我們使用設計模式對上面的程式碼進行優化

  • 建立一個簡單策略介面SimpleStrategy,其中的方法operate中可以傳入一個物件,然後就可以在這個介面的實現類中,進行過濾條件處理
public interface SimpleStrategy<T>{

    public boolean operate(T t);
}
  • 這樣我們就可以用一個全新的方法,去替換之前那些因為不斷增加的需求而寫的千篇一律的方法
public List<Student> filterStudentByStrategy(List<Student> students,SimpleStrategy<Student> strategy){
    List<Student> stus = new ArrayList<>();
    for (Student s : students){
        if(strategy.operate(s)){
            stus.add(s);
        }
    }
    return stus;
}

此時,我們看到只需要在方法中傳一個SimpleStrategy的一個實現類,就能自由的進行過濾了,測試程式碼如下:

@Test
public void getMoreThanThreeGrade(){
   List<Student> sts =  filterStudentByStrategy(students, new SimpleStrategy<Student>() {
        @Override
        public boolean operate(Student student) {
            return student.getGender() == 1;
        }
    });
}

雖然我們使用了策略模式,並通過匿名內部類的方式對學生資訊進行了過濾,可是在整個的程式碼,真正有用的程式碼其實就一句

student.getGender() == 1;

可是我們為了完成功能,卻又不得不寫那些重複冗餘的程式碼

  • 福音:使用Lambda表示式,不在寫重複冗餘的程式碼
List<Student> sts =  filterStudentByStrategy(students,(s)->s.getGender() == 1);

此時,我們最後的過濾程式碼就只有一行了,但是真的就完美了嗎?未必!!!

我們在上面還建立了一個策略的介面呢,而且還聲明瞭一個方法,程式碼還是很多,那麼有沒有什麼方式,不建立介面,也不用宣告一個過濾的方法,直接用一行程式碼就能實現上面的功能呢?

當然有,我們只需要使用Lambda表示式和Stream API就能完美的實現上述的功能了

List<Student> sts =  students.stream().filter(student -> student.getGender() == 1).collect(Collectors.toList());

這樣就真正的完美了!!!

原文連結http://blog.3811811.com/2018/08/02/%E7%BB%86%E8%AF%B4%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E4%BD%BF%E7%94%A8lambda%E8%A1%A8%E8%BE%BE%E5%BC%8F/