Java Lambda表達(dá)式詳解
Java Lambda表達(dá)式是JDK8引入的,是一個比較重要的特性
Lambda表達(dá)式簡介
Lambda 表達(dá)式是 JDK8 的一個新特性,也被稱為閉包,Lambda表達(dá)式允許把函數(shù)作為一個方法的參數(shù),即行為參數(shù)化,函數(shù)作為參數(shù)傳遞進(jìn)方法中。
Lambda表達(dá)式可以取代大部分的匿名內(nèi)部類,寫出更優(yōu)雅的 Java 代碼,尤其在集合的遍歷和其他集合操作中,可以極大地優(yōu)化代碼結(jié)構(gòu)。
Lambda表達(dá)式的作用
Java 8 引入的 Lambda表達(dá)式的主要作用就是簡化代碼,寫出更優(yōu)雅的代碼。
怎么一個簡化優(yōu)雅呢,舉一Lambda語法創(chuàng)建線程和匿名內(nèi)部類創(chuàng)建線程的例子,就非常清楚了。
1.匿名類創(chuàng)建線程
// JDK7匿名內(nèi)部類寫法
new Thread(new Runnable() {//接口名
????????@Override
????????public void run() {//方法名
????????????System.out.println("mikechen");
????????}
????});2.Lambda表達(dá)式創(chuàng)建線程
// JDK8 Lambda來創(chuàng)建線程
new Thread(() -> System.out.println("mikechen"));上述代碼跟匿名內(nèi)部類的作用是一樣的,但比匿名內(nèi)部類更進(jìn)一步,這里連接口名和函數(shù)名都一同省掉了,Lambda表達(dá)式可以取代匿名內(nèi)部類,寫出更優(yōu)雅的代碼。
Lambda表達(dá)式的語法
lambda 表達(dá)式的語法格式如下:

- ():左側(cè)部分指定了Lambda表達(dá)式需要的所有參數(shù)。
- ->:Lambda表達(dá)式的操作符或者箭頭操作符。
- {}:右側(cè)部分指定了Lambda體,即方法需要實(shí)現(xiàn)的內(nèi)容。

1.無參數(shù)
Lambda體只有一條語句:
示例:
()?->?System.out.println("mikechen");請注意,括號中沒有內(nèi)容。那就是表示lambda不帶任何參數(shù)。
2.一個參數(shù)
示例:
Consumer<String> con = (x) -> System.out.println(x);
當(dāng)lambda表達(dá)式是單個參數(shù)時,也可以省略括號,如下所示:
Consumer<String> con = x -> System.out.println(x);
3.多個參數(shù)
如果Java lambda表達(dá)式匹配的方法有多個參數(shù),則需要在括號內(nèi)列出這些參數(shù),代碼如下:
BinaryOperator<Integer> bo = (a, b) -> {
System.out.println("函數(shù)式接口");
return a + b;
};注意:僅當(dāng)方法是單個參數(shù)時,才可以省略括號。
4.指定參數(shù)類型
如果編譯器無法從lambda匹配的函數(shù)式接口抽象方法推斷參數(shù)類型,則有時可能需要為lambda表達(dá)式指定參數(shù)類型。
(Car car) -> System.out.println("The car is: " + car.getName());如你所見,car參數(shù)的類型(Car)寫在參數(shù)名稱的前面,就像在其他方法中聲明參數(shù)或?qū)涌谶M(jìn)行匿名實(shí)現(xiàn)時一樣。
5.只有一條語句時
當(dāng)Lambda體只有一條語句時,return和大括號可以省略,示例:
BinaryOperator<Integer> bo = (a, b) -> a + b;
6.參數(shù)類型不寫
Lambda表達(dá)式的參數(shù)列表的數(shù)據(jù)類型可以省略不寫,因?yàn)镴VM編譯器能夠通過上下文推斷出數(shù)據(jù)類型,這就是“類型推斷”,示例:
BinaryOperator<Integer> bo = (Integer a, Integer b) -> {
return a + b;
};等同于
BinaryOperator<Integer> bo = (a, b) -> {
return a + b;
};上述 Lambda 表達(dá)式中的參數(shù)類型都是由編譯器推斷得出,Lambda 表達(dá)式中無需指定類型,程序依然可以編譯,這是因?yàn)?javac 根據(jù)程序的上下文,在后臺推斷出了參數(shù)的類型。
Lambda 表達(dá)式的類型依賴于上下文環(huán)境,是由編譯器推斷出來的,這就是所謂的“類型推斷”。
7.Lambda表達(dá)式返回值
你可以從Java lambda表達(dá)式返回值,就像從方法中返回值一樣。你只需向lambda表達(dá)式主體添加一個return,如下所示:
(param) -> {
System.out.println("param: " + param);
return "return value";
}函數(shù)式接口
Lambda表達(dá)式需要函數(shù)式接口的支持,所以,我們有必要來說說什么是函數(shù)式接口。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}一種用于表示一個接口是Java語言規(guī)范定義的函數(shù)式接口的注解類型。
對于函數(shù)式接口,我們可以理解為只有一個抽象方法的接口,除此之外它和別的接口相比并沒有什么特殊的地方。
public interface MyFunctionInterface<T> {
public T getValue(T t);
}為了確保函數(shù)式接口的正確性,我們可以給這個接口添加@FunctionalInterface注解,這樣當(dāng)其中有超過一個抽象方法時就會報錯。
Unexpected @FunctionalInterface annotation @FunctionalInterface ^ WorkerInterface is not a functional interface multiple non-overriding abstract methods found in interface WorkerInterface 1 error
Java 8中每一個Lambda表達(dá)式必須有一個函數(shù)式接口與之對應(yīng),也就是說,只要一個對象是函數(shù)式接口的實(shí)例,那么該對象就可以用Lambda表達(dá)式來表示。
Lambda表達(dá)式的舉例
學(xué)習(xí) Lambda 表達(dá)式的最好方式是學(xué)習(xí)例子,下面我們看幾個比較常用的例子。
1.lambda創(chuàng)建線程
使用() -> {} 替代匿名類:
//JDK 8之前
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("使用匿名內(nèi)部類,開線程");
}
}).start();
//JDK 8 使用lambda表達(dá)式
new Thread(() -> System.out.println("使用lambda表達(dá)式,開線程")).start();2.lambda事件處理
使用lambda表達(dá)式如下所示寫出更好的事件偵聽器的代碼:
// Java 8之前:
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Button被點(diǎn)擊了使用老的方式!");
}
});
// Java 8方式:
button.addActionListener( (e) -> {
System.out.println("Button被點(diǎn)擊了使用Lambda表達(dá)式!");
});3.lambda遍歷List集合
集合的遍歷,采用lambda表達(dá)式會更簡潔:
// Java 8之前:
List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
for (String feature : features) {
System.out.println(feature);
}
// Java 8之后:
List 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);方法引用是使用兩個冒號::這個操作符號。
4.元素排序
之前我們?nèi)粢獮榧蟽?nèi)的元素排序,就必須調(diào)用 sort 方法,傳入比較器重寫 compare。
方法的比較器對象,現(xiàn)在我們還可以使用 lambda 表達(dá)式來簡化代碼。
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("d");
list.add("b");
list.add("c");
list.sort((o1,o2)->o1.compareTo(o2));
list.forEach(System.out::println);
}5.lambda Map
// 不使用lambda表達(dá)式為每個訂單加上12%的稅
List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
for (Integer cost : costBeforeTax) {
double price = cost + .12*cost;
System.out.println(price);
}
// 使用lambda表達(dá)式
List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
costBeforeTax.stream().map((cost) -> cost + .12*cost).forEach(System.out::println);6.lambda過濾String
// 創(chuàng)建一個字符串列表,每個字符串長度大于2
List<String> filtered = strList.stream().filter(x -> x.length()> 2).collect(Collectors.toList());
System.out.printf("Original List : %s, filtered list : %s %n", strList, filtered);7.lambda對集合應(yīng)用函數(shù)
// 將字符串換成大寫并用逗號鏈接起來
List<String> G7 = Arrays.asList("USA", "Japan", "France", "Germany", "Italy", "U.K.","Canada");
String G7Countries = G7.stream().map(x -> x.toUpperCase()).collect(Collectors.joining(", "));
System.out.println(G7Countries);8.lambda計算最大值、最小值、平均值
//獲取數(shù)字的個數(shù)、最小值、最大值、總和以及平均值
List<Integer> primes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
IntSummaryStatistics stats = primes.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("Highest prime number in List : " + stats.getMax());
System.out.println("Lowest prime number in List : " + stats.getMin());
System.out.println("Sum of all prime numbers : " + stats.getSum());
System.out.println("Average of all prime numbers : " + stats.getAverage());以上就是Java Lambda表達(dá)式詳解的詳細(xì)內(nèi)容,更多關(guān)于Java Lambda表達(dá)式詳解的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Idea導(dǎo)入多個maven項(xiàng)目到同一目錄下的方法示例
這篇文章主要介紹了Idea導(dǎo)入多個maven項(xiàng)目到同一目錄下,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07
Spring中的FactoryBean與ObjectFactory詳解
這篇文章主要介紹了Spring中的FactoryBean與ObjectFactory詳解,FactoryBean是一種特殊的bean,本身又是個工廠,實(shí)現(xiàn)了FactoryBean的bean會被注冊到容器中,需要的朋友可以參考下2023-12-12
Java中多線程Reactor模式的實(shí)現(xiàn)
多線程Reactor模式旨在分配多個reactor每一個reactor獨(dú)立擁有一個selector,本文就詳細(xì)的來介紹一下Java中多線程Reactor模式的實(shí)現(xiàn),需要的朋友可以參考下2021-12-12
Hibernate的一對一,一對多/多對一關(guān)聯(lián)保存的實(shí)現(xiàn)
本文主要介紹了Hibernate的一對一,一對多/多對一關(guān)聯(lián)保存的實(shí)現(xiàn),文中通過示例代碼介紹的很詳細(xì),感興趣的可以了解一下2021-09-09
使用Java Servlet生成動態(tài)二維碼的實(shí)現(xiàn)步驟
在現(xiàn)代互聯(lián)網(wǎng)時代,二維碼廣泛應(yīng)用于各個領(lǐng)域,包括支付、認(rèn)證、信息傳遞等,在Web開發(fā)中,通過Java Servlet生成動態(tài)二維碼是一個常見的需求,本文將介紹如何使用Java Servlet結(jié)合Google的ZXing庫生成動態(tài)二維碼,需要的朋友可以參考下2023-11-11
Spring Boot中操作使用Redis實(shí)現(xiàn)詳解
Spring Boot與Redis結(jié)合使用,通過使用Spring Data Redis來實(shí)現(xiàn)對Redis的操作,實(shí)現(xiàn)數(shù)據(jù)緩存和高效存儲,提高應(yīng)用程序的性能和響應(yīng)速度??梢岳肧pring Boot自帶的Redis Starter方便地集成和配置Redis2023-04-04

