java1.8新特性-lambda表示式
-
什麼是lambda表示式
長期以來,java為了保持簡單性和一致性,拒絕給變數賦值成“一段程式碼”,如果你想把“一段程式碼”賦給一個Java變數,應該怎麼做呢?這個“一段程式碼”就是lambda表示式。
-
為什麼引入lambda表示式
lambo表示式是一個可傳遞的程式碼塊,具體介紹語法之前,先來看看我們在java中的哪些地方用過這種程式碼塊。比如:
public static void main(String[] args) { String[] planets = new String[] { "宋大寶", "大瀋陽", "張三瘋子", "騰", "夏洛特", "趙四","劉小能" }; Arrays.sort(planets, new Comparator<String>() { @Override public int compare(String first, String second) { return first.length() - second.length(); } }); System.out.println(Arrays.toString(planets)); }
這段程式碼大家應該很熟悉,是用sort方法傳入一個Comparator物件進行list排序。
這其中有一個特點是構造出Comparator物件,compare包含一段程式碼來完成對“一段程式碼”的傳遞。
到目前為止,在java中傳遞一個程式碼段並不容易,不能直接傳遞程式碼段。java是一種面嚮物件語言,所以必須構造一個物件。這個物件的類需要有一個方法能包含所需的程式碼。
-
lambda表示式的語法
再來考慮上面討論排序的例子。我們傳入程式碼來檢查一個字串是否比另一個字串短。這裡要計算:
first.length() - second.length()
first和second是什麼?他們都是字串。java是一種強型別語言,所以我們還要指定它們的型別:
(String first, String second)
-> first.length() - second.length()
這就是你看到的第一個lambda表示式。lambda表示式就是一個程式碼塊,以及必須傳入程式碼的變數規範。
至此,我們可以看出lambda表示式形式:
(引數) -> 一個表示式或一段程式碼
如果想傳入的程式碼很多無法放在一個表示式中,就可以像寫方法一樣,把這些程式碼放在{}中,幷包含顯示的return語句。例如:
(String first, String second) -> { if(first.length() < second.length()) return -1; else if(first.length() > second.length()) return 1; else return 0; }
如果沒有引數怎麼辦?仍然要提供空括號,就像無引數方法一樣:
() -> { for(int i = 100; i>=0; i++) System.out.println(i); }
如果可以推匯出一個lambda表示式的引數型別,則可以忽略其型別。例如:
Comparator<String> comp = (first, second) -> first.length - second.length;
在這裡,編譯器可以推匯出first和second必然是字串。因為lambda表示式將賦給一個字串比較器。
如果方法只有一個引數,而且這個引數的型別可以推導得出。那麼甚至還可以省略小括號:
Timer t = new Timer(1000, event ->
System.out.println("The time is:" + new Date()));
例項程式碼:
package com.lambda;
import java.util.Arrays;
import java.util.Date;
import javax.swing.JOptionPane;
import javax.swing.Timer;
public class LambdaTest {
public static void main(String[] args) {
String[] planets = new String[] { "宋大寶", "大瀋陽", "張三瘋子", "騰", "夏洛特", "趙四", "劉小能" };
System.out.println(Arrays.toString(planets));
System.out.println("排序:");
Arrays.sort(planets);
System.out.println(Arrays.toString(planets));
System.out.println("根據長度排序:");
Arrays.sort(planets, (first, second) -> first.length() - second.length());
System.out.println(Arrays.toString(planets));
Timer t = new Timer(1000, event ->
System.out.println("The time is:" + new Date()));
t.start();
JOptionPane.showMessageDialog(null, "退出?");
System.exit(0);
}
}
-
ArrayList的removeIf方法
試想如果當前我們需要清除list中所有null值,可以有如下寫法:
List<String> list = new ArrayList<String>();
list.add("宋大寶");
list.add("大瀋陽");
list.add(null);
System.out.println("初始時:"+ list.toString());
for(int i=0;i<list.size();i++) {
if(list.get(i) == null) {
list.remove(i);
}
}
System.out.println("過濾完:" + list.toString());
java1.8的ArrayList新增了一個removeIf方法,一行程式碼搞定:
list.removeIf(e -> e == null);
removeIf方法的引數是一個Predicate介面。這個介面專門用來傳遞lambda表示式:
public interface Predicate < T >
{
boolean test ( T t ) ;
// Additional default and static methods
}