在這篇文章中,我想介紹一下Java 8最吸引人的新特性——lambda表達式。
先貼上lambda表達式的基本語法,有兩種形式:java
lambda容許把函數做爲一個方法的參數傳遞進方法中,體現了函數式編程思想。使用lambda表達式可使代碼變得更加簡潔緊湊。lambda表達式的本質只是一個所謂的「語法糖」,並無爲Java語言添加新的功能,而是對已有功能進行了封裝,由編譯器推斷並轉換爲常規的代碼,所以能夠用更少的代碼來實現一樣的功能。我我的以爲,lambda表達式雖好,但不要亂用,用在合適的地方,能夠有效減小代碼量,使代碼更加簡潔,而濫用只會下降代碼的可讀性,使程序難以調試和維護。那麼lambda表達式的應用場景是什麼呢?
網上有不少lambda表達式的例子,我看了半天,以爲無外乎就兩個場景(我的淺顯觀點......):
一是代替函數式接口。函數式接口簡單來講就是隻包含一個抽象方法的接口,好比Java標準庫中的java.lang.Runnable和java.util.Comparator都是典型的函數式接口。對於函數式接口,除了可使用Java中標準的方法來建立實現對象以外,還可使用lambda表達式來建立實現對象,這能夠在很大程度上簡化代碼的實現。在使用lambda表達式時,只須要提供形式參數和方法體。因爲函數式接口只有一個抽象方法,因此經過lambda表達式聲明的方法體確定是這個惟一的抽象方法的實現,並且形式參數的類型能夠根據方法的類型聲明進行自動推斷(即形式參數能夠省略類型)。
第二個場景,就是和集合配合使用。Java 8新增了兩個對集合數據進行批量操做的包:java.util.function和java.util.stream。能夠說,lambda表達式和stream是自Java語言添加泛型和註解以來最大的變化,lambda表達式很大程度上影響了咱們在處理集合時的編碼方式。express
下面,我經過幾個典型的例子帶你們領略lambda表達式的強悍:編程
傳統方式ide
public class runnableTest {
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
System.out.println("I am Hawk.");
}
}).start();
}
}
複製代碼
使用lambda表達式函數式編程
public class runnableTest {
public static void main(String[] args) {
new Thread(() ->
System.out.println("I am Hawk.")
).start();
}
}
複製代碼
經過這個例子,咱們也能夠進一步熟悉lambda表達式的聲明方式:由形式參數和方法體兩部分組成,中間經過「->」分隔。形式參數一般狀況下不須要包含類型聲明,能夠進行自動推斷。由於 System.out.println("I am Hawk.") 是單行語句,能夠不用花括號「{}」括起來,若是方法體包含多行語句,則須要用「{}」括起來。函數
關於Comparator的機制,不在咱們此次的討論範圍內,我有時間...額...大概會寫。總之,當咱們相比較的對象沒有實現Comparable接口時,可使用Comparator接口並實現其中的compare方法進行比較。好比說,有這樣一個Penple類:編碼
// 使用lombok註解自動生成構造器與get、set方法等
@Data
@NoArgsConstructor
@AllArgsConstructor
public class People {
private String name;
private Integer age;
}
複製代碼
如今我想按照年齡對People對象進行排序:
傳統方式spa
public class ComparatorTest {
public static void main(String[] args) {
List<People> peopleList = new ArrayList<>();
peopleList.addAll(Arrays.asList(new People("a", 20), new People("b", 21), new People("c", 22)));
Collections.sort(peopleList, new Comparator<People>() {
@Override
public int compare(People p1, People p2) {
return p1.getAge().compareTo(p2.getAge());
}
});
}
}
複製代碼
使用lambda表達式調試
// 方法一
public class ComparatorTest {
public static void main(String[] args) {
List<People> peopleList = new ArrayList<>();
peopleList.addAll(Arrays.asList(new People("a", 20), new People("b", 21), new People("c", 22)));
Collections.sort(peopleList, (p1, p2) ->
p1.getAge().compareTo(p2.getAge()));
}
}
// 方法二
public class ComparatorTest {
public static void main(String[] args) {
List<People> peopleList = new ArrayList<>();
peopleList.addAll(Arrays.asList(new People("a", 20), new People("b", 21), new People("c", 22)));
peopleList.sort(Comparator.comparing(People::getAge));
}
}
複製代碼
不知道你們咋想的,反正我當時知道還有方法二這種寫法時是真的驚了。感受Java 8中的集合類型在增長了lambda表達式的支持以後變得......emmm高深莫測。須要注意一點,在方法二中,還使用了Java 8的另外一個新特性——方法引用,就是那兩個冒號「::」(有點C++的趕腳)。方法引用能夠在不調用某個方法的狀況下引用一個方法,是另外一種實現函數式接口的方法,能夠進一步簡化代碼。code
傳統方法
public class foreachTest {
public static void main(String[] args) {
List<String> stringList = new ArrayList<>();
stringList.addAll(Arrays.asList("a", "b", "c"));
for (String str : stringList) {
System.out.println(str);
}
}
}
複製代碼
使用lambda表達式
public class foreachTest {
public static void main(String[] args) {
List<String> stringList = new ArrayList<>();
stringList.addAll(Arrays.asList("a", "b", "c"));
stringList.forEach(System.out::println);
}
}
複製代碼
額......先寫到這裏吧,由於stream部份內容較多,過幾天再補充完。此次主要介紹了使用lambda表達式的第一個場景——代替函數式接口。這是一個趨勢,但願你們在從此的編碼中,能逐漸拋棄匿名內部類,改用lambda這種更爲簡潔的寫法。下次我將重點介紹lambda在集合中的使用以及如何與stream進行配合。