詳解Java中的Lambda表達(dá)式
Java 目前已經(jīng)出到13的版本,但是國內(nèi)大部分公司應(yīng)該都停留在 Java 8 的版本(不敢承擔(dān)升級帶來的風(fēng)險(xiǎn))。在Java8中給我們帶來了 Lambda表達(dá)式和Stream流式操作,提供了函數(shù)式編程和簡化批處理操作。可能大家日常使用很多,但是很少去關(guān)注Lambda 和 Stream實(shí)現(xiàn)。本篇就帶著大家一起關(guān)注這兩塊知識,搬好小板凳我們一起看電視。
什么是Lambda
簡單來說,編程中提到的 lambda 表達(dá)式,通常是指需要一個(gè)函數(shù),但是又不想費(fèi)神去命名一個(gè)函數(shù)的場合下使用,也就是指匿名函數(shù)。
一般我們使用變量來進(jìn)行賦值操作:
但是在 Java8 之前是沒有提供將一個(gè)方法賦值給一個(gè)變量的操作:
在 JavaScript 中有 閉包的概念,所以 Java不甘落后,也去學(xué)習(xí)了人家,搞出了匿名函數(shù)的概念。
在Java 8里面,所有的Lambda的類型都是一個(gè)接口,而Lambda表達(dá)式本身,也就是”那段代碼“,需要是這個(gè)接口的實(shí)現(xiàn)。這是我認(rèn)為理解Lambda的一個(gè)關(guān)鍵所在,簡而言之就是,Lambda表達(dá)式本身就是一個(gè)接口的實(shí)現(xiàn)。
基本語法:
(parameters) -> { expression or statements }
示例:
// 無參數(shù), 返回1+2的結(jié)果 () -> 1+2; // 接收一個(gè)參數(shù)(數(shù)字類型),返回其2倍的值 x -> 2 * x; // 接收2個(gè)參數(shù)(數(shù)字),返回表達(dá)式運(yùn)算的結(jié)果 (x, y) -> x + y; // 多個(gè)語句要用大括號包裹, 并且返回值要用return指明 (x, y) -> { int result = x + y; System.out.print(result); return result; };
Lambda表達(dá)式有如下約定:
- 一個(gè) Lambda 表達(dá)式可以有零個(gè)或多個(gè)參數(shù);
- 參數(shù)的類型既可以明確聲明,也可以根據(jù)上下文來推斷。例如:(int a)與(a)效果相同;
- 所有參數(shù)需包含在圓括號內(nèi),參數(shù)之間用逗號相隔。例如:(a, b) 或 (int a, int b) 或 (String a, int b, float c);
- 空圓括號代表參數(shù)集為空。例如:() -> 42;
- 當(dāng)只有一個(gè)參數(shù),且其類型可推導(dǎo)時(shí),圓括號()可省略。例如:a -> return a*a;
- Lambda 表達(dá)式的主體可包含零條或多條語句;
- 如果 Lambda 表達(dá)式的主體只有一條語句,花括號{}可省略。匿名函數(shù)的返回類型與該主體表達(dá)式一致;
- 如果 Lambda 表達(dá)式的主體包含一條以上語句,則表達(dá)式必須包含在花括號{}中(形成代碼塊)。匿名函數(shù)的返回類型與代碼塊的返回類型一致,若沒有返回則為空。
@FunctionalInterface 是 Java 8 新加入的一種接口,用于指明該接口類型聲明是根據(jù) Java 語言規(guī)范定義的函數(shù)式接口。Java 8 還聲明了一些 Lambda 表達(dá)式可以使用的函數(shù)式接口,當(dāng)你注釋的接口不是有效的函數(shù)式接口時(shí),可以使用 @FunctionalInterface 解決編譯層面的錯(cuò)誤。
根據(jù)定義,函數(shù)式接口只能有一個(gè)抽象方法,如果你嘗試添加第二個(gè)抽象方法,將拋出編譯時(shí)錯(cuò)誤。例如:
@FunctionalInterface public interface DoSomethingInterface { void doSomeThing(); void doSomeThing1(); }
舉一個(gè)簡單使用的例子,首先定義一個(gè)接口:
@FunctionalInterface public interface DoSomethingInterface<T> { String doSomeThing(T t); }
這個(gè)接口里面只能有一個(gè)函數(shù),接口里是返回值為String類型的方法,那么下面使用它的時(shí)候就需要有返回值:
class MainTest{ public static void main(String[] args) { DoSomethingInterface<String> t = str -> { return str; }; String print = t.doSomeThing("print"); System.out.println(print); } }
t就相當(dāng)于是接口的具體實(shí)現(xiàn),那么使用 t.doSomeThing("print")就會去調(diào)用 t 的匿名函數(shù)執(zhí)行。從這段代碼看,如果我們有一個(gè)抽象類的具體實(shí)現(xiàn)邏輯相對簡單不用大段代碼的時(shí)候,可以使用 Lambda 表達(dá)式去實(shí)現(xiàn)具體的邏輯,這樣就不用new 多個(gè)類。
Java 8 內(nèi)置4大核心函數(shù)式接口
大家日常使用的List,Map,肯定大量使用了Stream流式處理,在流式處理中大量使用了Lambda,比如List的foreach方法就使用了Lambda表達(dá)式。Java8中抽象出來4類基本的函數(shù)式接口,日常開發(fā)中我們其實(shí)也是可以使用的。
函數(shù)式接口 | 參數(shù)類型 | 返回類型 | 用途 |
Consumer |
T | Void | void accept(T t) :將T 類型的參數(shù)應(yīng)用于該方法 |
Supplier |
T | T | T get():返回類型為T 的對象 |
Function<T,R> | T | R | R apply(T t):輸出T類型的參數(shù)返回R類型的結(jié)果 |
Predicate |
T | Boolean | boolean test(T t): 確定類型為T 的參數(shù)是否滿足test邏輯 |
以上4種類型是Java默認(rèn)提供的Lambda類,開箱即用。
Consumer使用:
public void test(){ save(user, t->{ saveUser(t); }); } public void save(User user, Consumer<User> consumer){ consumer.accept(user); }
Supplier使用:
public void test(){ Config config = getConfig(t -> { return getAllConfig(t); }); } public Config getConfig(Supplier<Config> supplier) { return supplier.get(); }
Function使用:
public void test(){ User user = getUser(t -> { return getUserByName(t); }); } public User getUser(Function<String, User> function) { return function.apply(t); }
Predicate使用:
public void test(){ boolean b = checkStatus(user, t -> { return checkUserExist(t); }); } public boolean checkStatus(User user, Predicate<User> predicate) { return predicate.test(user); }
以上關(guān)于Lambda就介紹到這里,大家應(yīng)該明白了它是干啥的了吧。閉包是不是也沒有這么難懂呢!聯(lián)想到List的foreach使用,大家有沒有沖動想自己實(shí)現(xiàn)一個(gè)Lambda在日常開發(fā)中炫一把(如果別人看不懂,會打你的)。
到此這篇關(guān)于詳解Java中的Lambda表達(dá)式的文章就介紹到這了,更多相關(guān)Java中的Lambda表達(dá)式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java同步鎖Synchronized底層源碼和原理剖析(推薦)
這篇文章主要介紹了Java同步鎖Synchronized底層源碼和原理剖析,釋放后,進(jìn)入減減操作、直到為0然后喚醒隊(duì)列,讓他們?nèi)帄Z鎖,循環(huán)前面步驟,對Java同步鎖Synchronized相關(guān)知識感興趣的朋友一起看看吧2022-05-05Spring?Cloud?Gateway?2.x跨域時(shí)出現(xiàn)重復(fù)Origin的BUG問題
這篇文章主要介紹了Spring?Cloud?Gateway?2.x跨域時(shí)出現(xiàn)重復(fù)Origin的BUG問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04JAVA中SSM框架的搭建實(shí)現(xiàn)CRUD的方法
這篇文章主要介紹了JAVA中SSM框架的搭建實(shí)現(xiàn)CRUD的方法,小編把運(yùn)行代碼列了出來,供大家參考。2017-11-11Java實(shí)現(xiàn)生成pdf并解決表格分割的問題
這篇文章主要為大家詳細(xì)介紹了如何利用Java實(shí)現(xiàn)生成pdf,并解決表格分割的問題,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-11-11SpringBoot統(tǒng)一返回處理出現(xiàn)cannot?be?cast?to?java.lang.String異常解決
這篇文章主要給大家介紹了關(guān)于SpringBoot統(tǒng)一返回處理出現(xiàn)cannot?be?cast?to?java.lang.String異常解決的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-09-09