細說為什麼要使用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());
這樣就真正的完美了!!!