Java的Lambda表達(dá)式使用及說(shuō)明
1. 介紹
- Lambda 表達(dá)式是 JavaSE8 中的一個(gè)重要的新特性
- Lambda 表達(dá)式允許你通過(guò)表達(dá)式來(lái)代替功能接口
- Lambda 表達(dá)式和方法一樣,它提供了一個(gè)正常的參數(shù)列表和一個(gè)使用這些參數(shù)的主體
- Lambda 表達(dá)式可以看作是一個(gè)匿名函數(shù),基于數(shù)學(xué)中的 λ 演算得名,也可以稱其為閉包
- Lambda 表達(dá)式允許把函數(shù)作為一個(gè)方法的參數(shù)
2. Lambda 表達(dá)式的語(yǔ)法
基本形式: Lambda 表達(dá)式由三部分組成:參數(shù)、->符號(hào)、方法體
(參數(shù)列表)->{方法體}
補(bǔ)充:
- Lambda 表達(dá)式的參數(shù)可以是零個(gè)或多個(gè)
- 參數(shù)的類型可以明確聲明,也可以不聲明,由 JVM 隱式的推斷,例如
(int a)和(a)效果相同 - 當(dāng)參數(shù)只有一個(gè),且類型可推導(dǎo)時(shí),可以省略括號(hào),例如
(a)與a效果相同 - 如果 Lambda 表達(dá)式的方法體只有一條語(yǔ)句時(shí),可以省略花括號(hào)
- 如果 Lambda 表達(dá)式的方法體只有一條語(yǔ)句,且為返回值的時(shí)候,可以省略 return
代碼示例:
// 不需要參數(shù),返回值為 2
()->2
// 接收一個(gè)參數(shù)(數(shù)字類型),返回值為其2倍的值
x->2*x
// 接收兩個(gè)參數(shù)(數(shù)字類型),并返回它們的和
(x,y)->x+y
// 接收兩個(gè) int 類型參數(shù),返回它們的乘積
(int x,int y)->x*y
// 接收一個(gè) String 對(duì)象,并在控制臺(tái)打印
(String s)->System.out.println(s)
3. 函數(shù)接口
如果一個(gè)接口中有且只有一個(gè) abstract 方法,稱這樣的接口為單接口。從 JDK8 開(kāi)始,Java 使用 Lambda 表達(dá)式,并將單接口稱為函數(shù)接口
注意:
- 如果一個(gè)接口只有一個(gè)抽象方法,那么該接口就是一個(gè)函數(shù)式接口
- 如果我們?cè)谀硞€(gè)接口上聲明了
@FunctionInterface注解,那么編譯器就會(huì)按照函數(shù)式接口的定義來(lái)要求該接口,因此這個(gè)接口只能有一個(gè)抽象方法,如果超過(guò),程序編譯時(shí)就會(huì)報(bào)錯(cuò)
示例代碼:
@functionInterface
interface A{
void test();
}
4. Lamdba 表達(dá)式的使用
接下來(lái)為大家演示 Lambda 表達(dá)式的使用
// 無(wú)返回值無(wú)參數(shù)
@FunctionalInterface interface NoParameterNoReturn { void test(); }
// 無(wú)返回值一個(gè)參數(shù)
@FunctionalInterface interface OneParameterNoReturn { void test(int a); }
// 無(wú)返回值多個(gè)參數(shù)
@FunctionalInterface interface MoreParameterNoReturn { void test(int a,int b); }
// 有返回值無(wú)參數(shù)
@FunctionalInterface interface NoParameterReturn { int test(); }
// 有返回值一個(gè)參數(shù)
@FunctionalInterface interface OneParameterReturn { int test(int a); }
// 有返回值多參數(shù)
@FunctionalInterface interface MoreParameterReturn { int test(int a,int b); }
public class TestDemo {
public static void main(String[] args) {
NoParameterNoReturn noParameterNoReturn = ()->{ System.out.println("無(wú)參數(shù)無(wú)返回值"); };
noParameterNoReturn.test();
OneParameterNoReturn oneParameterNoReturn = (int a)->{ System.out.println("無(wú)參數(shù)一個(gè)返回值:"+ a); };
oneParameterNoReturn.test(10);
MoreParameterNoReturn moreParameterNoReturn = (int a,int b)->{ System.out.println("無(wú)返回值多個(gè)參數(shù):"+a+" "+b); };
moreParameterNoReturn.test(20,30);
NoParameterReturn noParameterReturn = ()->{ System.out.println("有返回值無(wú)參數(shù)!"); return 40; };
//接收函數(shù)的返回值
int ret = noParameterReturn.test();
System.out.println(ret);
OneParameterReturn oneParameterReturn = (int a)->{ System.out.println("有返回值有參數(shù)!"); return a; };
ret = oneParameterReturn.test(50);
System.out.println(ret);
MoreParameterReturn moreParameterReturn = (int a,int b)->{ System.out.println("有返回值多個(gè)參數(shù)!"); return a+b; };
ret = moreParameterReturn.test(60,70);
System.out.println(ret);
}
}
5. 變量捕獲
5.1 介紹
Java 中的局部類和匿名類都存在變量捕獲
只有理解了什么是變量捕獲之后,我們才能更好地理解 Lambda 表達(dá)式的作用域,因?yàn)?Lambda 表達(dá)式也存在變量捕獲。
5.2 匿名內(nèi)部類的變量捕獲
class A {
public void func(){
System.out.println("func()");
}
}
public class TestDemo {
public static void main(String[] args) {
int a = 100;
new Test(){
@Override public void func() {
System.out.println("我是內(nèi)部類,且重寫了func這個(gè)方法!");
System.out.println("我是捕獲到變量 a == "+a +" 我是一個(gè)常量,或者是一個(gè)沒(méi)有改變過(guò)值的變量!");
}
};
}
}
上述代碼中的變量 a 就是捕獲變量,這個(gè)變量要么是被 final 修飾,要么就要保證此變量在匿名內(nèi)部類中使用時(shí)沒(méi)有被修改,如果修改就會(huì)編譯出錯(cuò)
5.3 Lambda 的變量捕獲
在 Lambda 中也可以進(jìn)行變量捕獲
@FunctionalInterface interface A {
void test();
}
public static void main(String[] args) {
int a = 10;
NoParameterNoReturn noParameterNoReturn = ()->{
// a = 99; 如果修改a,則會(huì)報(bào)錯(cuò)
System.out.println("捕獲變量:"+a);
};
noParameterNoReturn.test();
}
6. Lambda 在集合中的使用
為了能夠讓 Lambda 和 Java 的集合類集更好的一起使用,集合當(dāng)中也新增了部分接口,以便與 Lambda 表達(dá)式對(duì)接
| 對(duì)應(yīng)的接口 | 新增的方法 |
|---|---|
| Collection | removeIf()、spliterator()、stream()、parallelStream()、forEach() |
| List | replaceAll()、sort() |
| Map | getDefault()、forEach()、replaceAll()、putIfAbsent()、remove()、replace()、computeIfAbsent()、computeIfPresent()、compute()、merge() |
補(bǔ)充:
Collection 的 forEach() 方法是從接口 java.lang.Interable 繼承的
6.1 Collection 接口
使用 forEach() 方法進(jìn)行演示
forEach()源碼:

代碼示例: 使用匿名內(nèi)部類
public class TestDemo{
public static void main(String[] args) {
List<String> list=new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.print(s+" ");
}
});
}
}
// 結(jié)果為:aaa bbb ccc
代碼示例: 使用 Lambda
public class TestDemo{
public static void main(String[] args) {
List<String> list=new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.forEach(s -> System.out.print(s+" "));
}
}
// 結(jié)果為:aaa bbb ccc
6.2 List 接口
使用 sort() 方法進(jìn)行演示
sort()源碼:

代碼示例: 使用匿名內(nèi)部類
public class TestDemo{
public static void main(String[] args) {
List<String> list=new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
System.out.println(list);
}
}
// 結(jié)果為:[aaa, bbb, ccc]
代碼示例: 使用 Lambda
public class TestDemo{
public static void main(String[] args) {
List<String> list=new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.sort((String o1,String o2)->o1.compareTo(o2));
System.out.println(list);
}
}
// 結(jié)果為:[aaa, bbb, ccc]
6.3 Map 接口
使用 HashMap 的 forEach() 方法進(jìn)行演示
HashMap的forEach()源碼:

代碼示例: 使用匿名內(nèi)部類
public class TestDemo{
public static void main(String[] args) {
Map<Integer,String> map=new HashMap<>();
map.put(1,"aaa");
map.put(2,"222");
map.put(3,"333");
map.forEach(new BiConsumer<Integer, String>() {
@Override
public void accept(Integer integer, String s) {
System.out.println("Key="+integer+" Value="+s);
}
});
}
}
/** 結(jié)果為:
Key=1 Value=aaa
Key=2 Value=222
Key=3 Value=333
*/
代碼示例: 使用 Lambda
public class TestDemo{
public static void main(String[] args) {
Map<Integer,String> map=new HashMap<>();
map.put(1,"aaa");
map.put(2,"222");
map.put(3,"333");
map.forEach((Integer integer,String s)->
System.out.println("Key="+integer+" Value="+s));
}
}
/** 結(jié)果為:
Key=1 Value=aaa
Key=2 Value=222
Key=3 Value=333
*/
7. Lambda 表達(dá)式的優(yōu)點(diǎn)和缺點(diǎn)
優(yōu)點(diǎn):
- 代碼簡(jiǎn)潔,開(kāi)發(fā)迅速
- 方便函數(shù)式編程
- 容易進(jìn)行并行計(jì)算
- Java 引入 Lambda,改善了集合操作
缺點(diǎn):
- 代碼可讀性變差
- 在非并行計(jì)算中,很多計(jì)算未必有傳統(tǒng) for 循環(huán)性能高
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring使用@Conditional進(jìn)行條件裝配的實(shí)現(xiàn)
在spring中有些bean需要滿足某些環(huán)境條件才創(chuàng)建某個(gè)bean,這個(gè)時(shí)候可以在bean定義上使用@Conditional注解來(lái)修飾,所以本文給大家介紹了Spring使用@Conditional進(jìn)行條件裝配的實(shí)現(xiàn),文中通過(guò)代碼示例給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12
java.net.http.HttpClient使用示例解析
這篇文章主要為大家介紹了java.net.http.HttpClient使用示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
SpringBoot返回對(duì)象時(shí),如何將Long類型轉(zhuǎn)換為String
這篇文章主要介紹了SpringBoot返回對(duì)象時(shí),實(shí)現(xiàn)將Long類型轉(zhuǎn)換為String,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
SpringBoot中集成Swagger2及簡(jiǎn)單實(shí)用
使用Swagger你只需要按照它的規(guī)范去定義接口及接口相關(guān)的信息,再通過(guò)Swagger衍生出來(lái)的一系列項(xiàng)目和工具,就可以做到生成各種格式的接口文檔,以及在線接口調(diào)試頁(yè)面等等,這篇文章主要介紹了SpringBoot中集成Swagger2,需要的朋友可以參考下2023-06-06
Spring Data JPA 之 JpaRepository的使用
這篇文章主要介紹了Spring Data JPA 之 JpaRepository的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
Maven中錯(cuò)誤使用parent.relativePath導(dǎo)致構(gòu)建失敗問(wèn)題
這篇文章主要介紹了Maven中錯(cuò)誤使用parent.relativePath導(dǎo)致構(gòu)建失敗問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08

