背景
在使用idea的時候,idea會給出一些優化建議,例如:
點開后,會變成原本的語句:
為啥這兩句話會等價呢,于是就研究研究了這個lambda表達式的一些基本的概念
概念
首先呢,lambda表達式使用要求jdk≥1.8。
lambda表達式是匿名方法,它提供了輕量級的語法,從而解決了匿名內部類帶來的“高度問題”。
由參數列表、箭頭符號->和函數體組成。函數體既可以是一個表達式,也可以是一個語句塊。
例如:
() -> System.out.println("線程建立")
( x, y ) -> x + y
能干什么用呢,我的理解是,從效果上看,基本上等價于返回一個接口類,這個接口類只能有一個方法,方法的參數列表就是->前面的參數列表,后面就是這個方法的函數體。
例如,比較常見的創建一個線程并啟動,一般是這么寫:
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("線程建立");
}
}).start();
這里Thread構造函數需要傳遞一個Runnable接口類,Runnable接口類實際上就有一個唯一的方法,就是run。所以Runnable這個匿名類就可以改寫為lambda表達式方法:
new Thread(() -> {
System.out.println("線程建立");
}).start();
另外還有個特性,如果方法塊中只有一句話,可以把大括號和分號去掉
new Thread(() -> System.out.println("線程建立")).start();
于是我們就把上面六行代碼縮減成一行了。很酷炫有沒有。
進階
簡單介紹完后,下面先簡單介紹下其他有用的點:
在JDK1.8中,List等集合類適配了一些配合lambda表達式的方法,比如forEach等,配合lambda表達式可以方便的進行一些遍歷等操作
List<Integer> list = new ArrayList<Integer>();
for (int i = 1; i < 101; i++) {
list.add(i);
}
list.forEach(s -> System.out.println(s));
forEach定義在Iterable接口中
可以看到,有個accept方法(default關鍵字是JDK1.8特性,可以給接口添加默認方法,類似抽象類,這個以后再說,先不考慮default關鍵字標注的方法),
Consumer接口,只有一個方法,所以當我們調用list.forEach(s -> System.out.println(s));也就是相當于實現了一個匿名類,類實現了Consumer接口,類似下面的代碼:
list.forEach(new Consumer<Integer>() {
@Override
public void accept(Integer s) {
System.out.println(s);
}
});
實際上發現,如果在方法中使用lambda表達式,需要參數的接口類,是函數式接口,通俗講就是函數式接口(Functional Interface)就是一個具有一個方法的普通接口。
像
- java.lang.Runnable
- java.util.concurrent.Callable
- java.util.Comparator
- java.io.FileFilter
還有很多,jdk也增加了許多,可以參考Java 8 函數式接口。
回到本文開頭,也就不難看出為啥這兩個等價了
因為RowMapper只有一個方法,mapRow,所以也就可以看作為一個函數式接口,那么就可以用lambda表達式進行編寫了,(result, i)->{...}
。
其他
lambda如果配合1.8新增的集合類的Stream,還可以更方便的處理集合類的需求,這個有機會再分享吧。
本人由于研究使用lambda表達式時間也不太長,如果有錯誤還希望指出來,共同進步哈~