0x00 例子
1、 用lambda表達(dá)式實現(xiàn)Runnable
import java.util.Arrays;
/**
* Created by haicheng.lhc on 10/04/2017.
*
* @author haicheng.lhc
* @date 2017/04/10
*/
public class Test {
public static void main(String[] args) {
// java8之前
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Before Java8, too much code for too little to do");
}
}).start();
// java8之后
new Thread( () -> System.out.println("In Java8, Lambda expression rocks !!") ).start();
}
}
輸出結(jié)果:
2汰翠、使用lambda表達(dá)式對列表進(jìn)行迭代
import java.util.Arrays;
import java.util.List;
/**
* Created by haicheng.lhc on 10/04/2017.
*
* @author haicheng.lhc
* @date 2017/04/10
*/
public class Test {
public static void main(String[] args) {
// Java 8之前:
List<String> features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
for (String feature : features) {
System.out.println(feature);
}
// Java 8之后:
List<String> features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
features.forEach(n -> System.out.println(n));
// 使用Java 8的方法引用更方便临谱,方法引用由::雙冒號操作符標(biāo)示,
features.forEach(System.out::println);
}
}
3奴璃、使用lambda表達(dá)式和函數(shù)式接口Predicate
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
/**
* Created by haicheng.lhc on 13/04/2017.
*
* @author haicheng.lhc
* @date 2017/04/13
*/
public class TT {
public static void main(String args[]) {
List<String> languages = Arrays.asList("Java", "Scala", "C++", "Haskell", "Lisp");
System.out.println("Languages which starts with J :");
filter(languages, (str) -> str.startsWith("J"));
System.out.println("Languages which ends with a ");
filter(languages, (str) -> str.endsWith("a"));
System.out.println("Print all languages :");
filter(languages, (str) -> true);
System.out.println("Print no language : ");
filter(languages, (str) -> false);
System.out.println("Print language whose length greater than 4:");
filter(languages, (str) -> str.length() > 4);
}
public static void filter(List<String> names, Predicate<String> condition) {
for (String name : names) {
if (condition.test(name)) {
System.out.println(name + " ");
}
}
}
}
其中的filter可以實現(xiàn)的更加優(yōu)雅
public static void filter(List<String> names, Predicate<String> condition) {
names.stream().filter((name) -> (condition.test(name))).forEach((name) -> {
System.out.println(name + " ");
});
}
4悉默、通過過濾創(chuàng)建一個String列表
過濾是Java開發(fā)者在大規(guī)模集合上的一個常用操作,而現(xiàn)在使用lambda表達(dá)式和流API過濾大規(guī)模數(shù)據(jù)集合是驚人的簡單苟穆。流提供了一個 filter() 方法抄课,接受一個 Predicate 對象,即可以傳入一個lambda表達(dá)式作為過濾邏輯雳旅。下面的例子是用lambda表達(dá)式過濾Java集合跟磨,將幫助理解
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* Created by haicheng.lhc on 13/04/2017.
*
* @author haicheng.lhc
* @date 2017/04/13
*/
public class T2 {
public static void main(String[] args) {
List<String> strList = Arrays.asList("Java", "Scala", "C", "Haskell", "Lisp");
// 創(chuàng)建一個字符串列表,每個字符串長度大于2
List<String> filtered = strList.stream().filter(x -> x.length()> 2).collect(Collectors.toList());
System.out.printf("Original List : %s %n filtered list : %s %n", strList, filtered);
}
}
0x01 lambda表達(dá)式語法
(params) -> expression
(params) -> statement
(params) -> { statements }
如果只有一個參數(shù)攒盈,可以不寫()
0x02 lambda表達(dá)式和要點
- lambda表達(dá)式僅能放入如下代碼:
預(yù)定義使用了 @Functional 注釋的函數(shù)式接口抵拘,自帶一個抽象函數(shù)的方法,或者SAM(Single Abstract Method 單個抽象方法)類型型豁。
這些稱為lambda表達(dá)式的目標(biāo)類型僵蛛,可以用作返回類型尚蝌,或lambda目標(biāo)代碼的參數(shù)。例如充尉,若一個方法接收Runnable飘言、Comparable或者 Callable 接口,都有單個抽象方法驼侠,可以傳入lambda表達(dá)式姿鸿。類似的,如果一個方法接受聲明于 java.util.function 包內(nèi)的接口倒源,例如 Predicate苛预、Function、Consumer 或 Supplier笋熬,那么可以向其傳lambda表達(dá)式碟渺。 - lambda表達(dá)式內(nèi)可以使用方法引用,僅當(dāng)該方法不修改lambda表達(dá)式提供的參數(shù)突诬。本例中的lambda表達(dá)式可以換為方法引用苫拍,因為這僅是一個參數(shù)相同的簡單方法調(diào)用。
list.forEach(n -> System.out.println(n));
list.forEach(System.out::println); // 使用方法引用
若對參數(shù)有任何修改旺隙,則不能使用方法引用绒极,而需鍵入完整地lambda表達(dá)式,如下所示:
list.forEach((String s) -> System.out.println("*" + s + "*"));
- lambda內(nèi)部可以使用靜態(tài)蔬捷、非靜態(tài)和局部變量垄提,這稱為lambda內(nèi)的變量捕獲。
- Lambda表達(dá)式在Java中又稱為閉包或匿名函數(shù)
- Lambda方法在編譯器內(nèi)部被翻譯成私有方法周拐,并派發(fā) invokedynamic 字節(jié)碼指令來進(jìn)行調(diào)用铡俐。
- lambda表達(dá)式有個限制,那就是只能引用 final 或 final 局部變量妥粟,這就是說不能在lambda內(nèi)部修改定義在域外的變量审丘。如下代碼會編譯報錯
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* Created by haicheng.lhc on 13/04/2017.
*
* @author haicheng.lhc
* @date 2017/04/13
*/
public class T2 {
public static void main(String[] args) {
List<Integer> primes = Arrays.asList(new Integer[]{2, 3,5,7});
int factor = 2;
primes.forEach(element -> { factor++; });
}
}
0x03 函數(shù)式開發(fā)
0x04 函數(shù)接口
- lambda表達(dá)式的目標(biāo)是函數(shù)接口。所以我們要了解一下啥是函數(shù)接口
- 學(xué)習(xí)資料
- 函數(shù)接口指的是只有一個函數(shù)的接口勾给,這樣的接口可以隱式轉(zhuǎn)換為Lambda表達(dá)式滩报。
java.lang.Runnable
和java.util.concurrent.Callable
是函數(shù)式接口的最佳例子 - Java 8 提供了一個特殊的注解
@FunctionalInterface
來標(biāo)明一個接口是函數(shù)接口
package java.lang;
/**
*
* @author Arthur van Hoff
* @see java.lang.Thread
* @see java.util.concurrent.Callable
* @since JDK1.0
*/
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
- 不過有一點需要注意,默認(rèn)方法和靜態(tài)方法不會破壞函數(shù)式接口的定義