好程序員Java教程分享Java8.0新特性之Lambda表達(dá)式:Java 8?已經(jīng)發(fā)布很久了,很多報(bào)道表明Java 8?是一次重大的版本升級(jí)。本篇文章,主要給大家介紹的是lambda表達(dá)式。
創(chuàng)新互聯(lián)擁有網(wǎng)站維護(hù)技術(shù)和項(xiàng)目管理團(tuán)隊(duì),建立的售前、實(shí)施和售后服務(wù)體系,為客戶提供定制化的成都網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、網(wǎng)站維護(hù)、服務(wù)器托管解決方案。為客戶網(wǎng)站安全和日常運(yùn)維提供整體管家式外包優(yōu)質(zhì)服務(wù)。我們的網(wǎng)站維護(hù)服務(wù)覆蓋集團(tuán)企業(yè)、上市公司、外企網(wǎng)站、商城網(wǎng)站定制開發(fā)、政府網(wǎng)站等各類型客戶群體,為全球1000多家企業(yè)提供全方位網(wǎng)站維護(hù)、服務(wù)器維護(hù)解決方案。
Lambda表達(dá)式
Lambda表達(dá)式(也稱為閉包)是Java 8中最大和最令人期待的語(yǔ)言改變。它允許我們將函數(shù)當(dāng)成參數(shù)傳遞給某個(gè)方法,或者把代碼本身當(dāng)作數(shù)據(jù)處理:函數(shù)式開發(fā)者非常熟悉這些概念。
很多JVM平臺(tái)上的語(yǔ)言(Groovy、Scala等)從誕生之日就支持Lambda表達(dá)式,但是Java開發(fā)者沒(méi)有選擇,只能使用匿名內(nèi)部類代替Lambda表達(dá)式。
Lambda的設(shè)計(jì)耗費(fèi)了很多時(shí)間和很大的社區(qū)力量,最終找到一種折中的實(shí)現(xiàn)方案,可以實(shí)現(xiàn)簡(jiǎn)潔而緊湊的語(yǔ)言結(jié)構(gòu)。而lambda表達(dá)式的使用需要和函數(shù)式接口結(jié)合。
1.函數(shù)式接口
1.1.概念
函數(shù)式接口在Java中是指:有且僅有一個(gè)抽象方法的接口。 函數(shù)式接口,即適用于函數(shù)式編程場(chǎng)景的接口。而Java中的函數(shù)式編程體現(xiàn)就是Lambda,所以函數(shù)式接口就是可 以適用于Lambda使用的接口。只有確保接口中有且僅有一個(gè)抽象方法,Java中的Lambda才能順利地進(jìn)行推導(dǎo)。 備注:“語(yǔ)法糖”是指使用更加方便,但是原理不變的代碼語(yǔ)法。例如在遍歷集合時(shí)使用的for-each語(yǔ)法,其實(shí) 底層的實(shí)現(xiàn)原理仍然是迭代器,這便是“語(yǔ)法糖”。從應(yīng)用層面來(lái)講,Java中的Lambda可以被當(dāng)做是匿名內(nèi)部 類的“語(yǔ)法糖”,但是二者在原理上是不同的。
1.2,格式
只要確保接口中有且僅有一個(gè)抽象方法即可:
1.?修飾符?interface?接口名稱?{ ??????????
2. ????public abstract?返回值類型 方法名稱(可選參數(shù)信息); ?
3. } ?
1.3 @FunctionalInterface注解
與?@Override?注解的作用類似,Java 8中專門為函數(shù)式接口引入了一個(gè)新的注解:?@FunctionalInterface?。該注解可用于一個(gè)接口的定義上:
1. @FunctionalInterface ?
2. public interface MyFunctionalInterface { ?
3. ????void myMethod(); ?
4. }
一旦使用該注解來(lái)定義接口,編譯器將會(huì)強(qiáng)制檢查該接口是否確實(shí)有且僅有一個(gè)抽象方法,否則將會(huì)報(bào)錯(cuò)。需要注?意的是,即使不使用該注解,只要滿足函數(shù)式接口的定義,這仍然是一個(gè)函數(shù)式接口,使用起來(lái)都一樣.
2.函數(shù)式接口的使用
2.1函數(shù)式接口作為參數(shù),方法不帶參數(shù)
1. //定義函數(shù)式接口 ?
2. public interface MyInterface{ ?
3. ?????
4. ????public abstract void show(); ?
5. ?????
6. } ?
7. ??
8. //使用(匿名內(nèi)部類對(duì)象/函數(shù)式) ??
9. public class Demo01 { ?
10. ??
11. ????public static void main(String[] args) { ?
12. ????????method01(new MyInterface01() { ?
13. ??
14. ????????????@Override ?
15. ????????????public void show() { ?
16. ????????????????System.out.println("你好,函數(shù)式接口"); ?
17. ????????????} ?
18. ????????}); ?
19. ????????//?函數(shù)式 ?
20. ????????method01(() -> { ?
21. ????????????System.out.println("你好,函數(shù)式接口"); ?
22. ????????}); ?
23. ????????//?函數(shù)式簡(jiǎn)寫(如果方法體中只有一句代碼) ?
24. ????????method01(() -> System.out.println("你好,函數(shù)式接口")); ?
25. ????} ?
26. ??
27. ????public static void method01(MyInterface01 inter) { ?
28. ????????inter.show(); ?
29. ????} ?
30. ??
31. }
函數(shù)式接口的優(yōu)勢(shì)
函數(shù)式接口比匿名內(nèi)部類對(duì)象產(chǎn)生更少的字節(jié)碼對(duì)象,提升java執(zhí)行效率.
2.2,?函數(shù)式接口作為參數(shù),方法帶參數(shù)
1. //定義函數(shù)式接口 ?
2. ????public interface MyInterface02 { ?
3. ??
4. ????????public abstract void show(String msg1, String msg2); ?
5. ??
6. ????} ?
7. ??
8. ????//使用函數(shù)式接口 ?
9. ????public static void main(String[] args) { ?
10. ????????//匿名內(nèi)部類對(duì)象 ?
11. ????????method01(new MyInterface02() { ?
12. ??
13. ????????????@Override ?
14. ????????????public void show(String msg1, String msg2) { ?
15. ????????????????System.out.println(msg1 + msg2); ?
16. ????????????} ?
17. ????????}); ?
18. ????????//函數(shù)式完整 ?
19. ????????method01((String msg1, String msg2) -> { ?
20. ????????????System.out.println(msg1 + msg2); ?
21. ????????}); ?
22. ????????//函數(shù)式簡(jiǎn)寫 ?
23. ????????method01((msg1, msg2) -> System.out.println(msg1 + msg2)); ?
24. ??
25. ????} ?
26. ??
27. ????public static void method01(MyInterface02 inter) { ?
28. ????????inter.show("hello", "函數(shù)式"); ?
29. ????}
2.3,?函數(shù)式接口作為返回值,方法不帶參數(shù)
1. ???//定義函數(shù)式接口 ?
2. ???public interface MyInterface02 { ?
3. ??
4. ????public abstract void show(String msg1, String msg2); ?
5. ??
6. ???} ?
7. public static void main(String[] args) { ?
8. ??
9. ????getInter1().show("你好", "函數(shù)式"); ?
10. ????getInter2().show("你好", "函數(shù)式"); ?
11. ??
12. } ?
13. ??
14. //?函數(shù)式完整 ?
15. public static MyInterface02 getInter1() { ?
16. ??
17. ????return (String msg1, String msg2) -> { ?
18. ????????System.out.println(msg1 + msg2); ?
19. ????}; ?
20. } ?
21. ??
22. //?函數(shù)式簡(jiǎn)寫 ?
23. public static MyInterface02 getInter2() { ?
24. ??
25. ????return (msg1, msg2) -> System.out.println(msg1 + msg2); ?
26. } ?
3.函數(shù)式編程應(yīng)用場(chǎng)景
3.1,概念
在兼顧面向?qū)ο筇匦缘幕A(chǔ)上,Java語(yǔ)言通過(guò)Lambda表達(dá)式使用函數(shù)式接口,就叫做函數(shù)式編程
3.2,?使用lambada作為參數(shù)
如果拋開實(shí)現(xiàn)原理不說(shuō),Java中的Lambda表達(dá)式可以被當(dāng)作是匿名內(nèi)部類的替代品。如果方法的參數(shù)是一個(gè)函數(shù) 式接口類型,那么就可以使用Lambda表達(dá)式進(jìn)行替代。
1. public class Demo04Runnable{ ?
2. ????private static void startThread(Runnable task){ ??
3. ????????new Thread(task).start(); ??
4. ????} ???????
5. ????public static void main(String[] args) { ??
6. ????????startThread(()‐>System.out.println("線程執(zhí)行")); ??
7. ????} ??
8. } ?
3.3,?使用函數(shù)式接口作為返回值
如果一個(gè)方法的返回值類型是一個(gè)函數(shù)式接口,那么就可以直接返回一個(gè)Lambda表達(dá)式。
1. public class Demo06Comparator { ?
2. ??
3. ????private static Comparator<Integer> getComparator(){ ?
4. ????????return (num1,num2)‐> num1 - num2; ?
5. ????} ?
6. ?????
7. ????public static void main(String[] args) { ?
8. ????????Integer[] array = {3,2,1}; ??
9. ????????Arrays.sort(array, getComparator()); ??
10. ????????//遍歷數(shù)組 ?
11. ????} ??
12. }
3.4,?函數(shù)式接口的方法有返回值
1. public static void main(String[] args) { ?
2. ??
3. ????????showMsg(new MyInterface03() { ?
4. ??
5. ????????????@Override ?
6. ????????????public String getMsg() { ?
7. ????????????????return "hello functional interface"; ?
8. ????????????} ?
9. ????????}); ?
10. ??
11. ????????// lambada表達(dá)式 ?
12. ????????showMsg(() -> { ?
13. ??
14. ????????????return "hello1 functional interface"; ?
15. ????????}); ?
16. ??
17. ????????// lambda表達(dá)式簡(jiǎn)寫 ?
18. ????????showMsg(() -> "hello1 functional interface"); ?
19. ??
20. ????} ?
21. ??
22. ????public static void showMsg(MyInterface03 inter) { ?
23. ????????String msg = inter.getMsg(); ?
24. ????????System.out.println(msg); ?
25. ????}
4.常用函數(shù)式接口(Supplier接口)
JDK提供了大量常用的函數(shù)式接口以豐富Lambda的典型使用場(chǎng)景,它們主要在?java.util.function?包中被提供。 下面是簡(jiǎn)單的幾個(gè)接口及使用示例。
4.1,Supplier接口 ?
java.util.function.Supplier<T>?接口僅包含一個(gè)無(wú)參的方法:?T get()?。用來(lái)獲取一個(gè)泛型參數(shù)指定類型的對(duì)象數(shù)據(jù)。由于這是一個(gè)函數(shù)式接口,這也就意味著對(duì)應(yīng)的Lambda表達(dá)式需要“對(duì)外提供”一個(gè)符合泛型類型的對(duì)象數(shù)據(jù)
4.2,基本使用
1. private static String getString(Supplier<String> function ){ ?
2. ????return function.get(); ?
3. } ?
4. public static void main(String[] args){ ?
5. ????String msgA="Hello"; ?
6. ????String msgB="World"; ?
7. ????System.out.println(getString(()->msgA+msgB)); ?
8. } ?
4.2,綜合案例
需求:使用?Supplier?接口作為方法參數(shù)類型,通過(guò)Lambda表達(dá)式求出int數(shù)組中的最大值。提示:接口的泛型請(qǐng)使用?java.lang.Integer?類。
1. public static void main(String[] args) { ?
2. ????Integer max = getMax(()->{ ?
3. ????????Integer[] nums = {1,2,3,4}; ?
4. ????????int max2 = nums[0]; ?
5. ????????for (Integer num : nums) { ?
6. ????????????if(max2 < num){ ?
7. ????????????????max2 = num; ?
8. ????????????} ?
9. ????????} ?
10. ????????return max2; ?
11. ????}); ?
12. ????System.out.println(max); ?
13. } ?
14. ??
15. public static Integer getMax(Supplier<Integer> supplier){ ?
16. ????return supplier.get(); ?
17. } ?
5.常用函數(shù)式接口(Consumer接口)
5.1,Consumer接口 ?
java.util.function.Consumer<T>?接口則正好與Supplier接口相反,它不是生產(chǎn)一個(gè)數(shù)據(jù),而是消費(fèi)一個(gè)數(shù)據(jù), 其數(shù)據(jù)類型由泛型決定
5.2,accept方法 ??
Consumer?接口中包含抽象方法?void accept(T t)?,意為消費(fèi)一個(gè)指定泛型的數(shù)據(jù)。基本使用如:
1. public static void main(String[] args) { ?
2. ????consumeString((msg)->System.out.println(msg)); ?
3. } ?
4. ??
5. ??
6. public static void consumeString(Consumer<String> consumer){ ?
7. ?????consumer.accept("hello"); ?
8. } ?
5.3, andThen方法 ??
如果一個(gè)方法的參數(shù)和返回值全都是?Consumer?類型,那么就可以實(shí)現(xiàn)效果:消費(fèi)數(shù)據(jù)的時(shí)候,首先做一個(gè)操作, 然后再做一個(gè)操作,實(shí)現(xiàn)組合。而這個(gè)方法就是?Consumer?接口中的default方法?andThen
1. default Consumer<T> andThen(Consumer<? super T> after) { ?
2. ????Objects.requireNonNull(after); ?
3. ????return (T t) -> { accept(t); after.accept(t); }; ?
4. } ?
注: java.util.Objects?的?requireNonNull?靜態(tài)方法將會(huì)在參數(shù)為null時(shí)主動(dòng)拋出?NullPointerException?異常。這省去了重復(fù)編寫if語(yǔ)句和拋出空指針異常的麻煩。
需求:先打印大寫HELLO,再打印小寫hello
1. public static void main(String[] args) { ?
2. ????consumeString((msg) -> System.out.println(msg.toUpperCase()), ??
3. ????????????(msg) -> System.out.println(msg.toLowerCase())); ?
4. } ?
5. ??
6. public static void consumeString(Consumer<String> consumer1, Consumer<String> consumer2) { ?
7. ????consumer1.andThen(consumer2).accept("hello"); ?
8. } ?
6.常用函數(shù)式接口(Predicate接口)
有時(shí)候我們需要對(duì)某種類型的數(shù)據(jù)進(jìn)行判斷,從而得到一個(gè)boolean值結(jié)果。這時(shí)可以使用?java.util.function.Predicate<T>?接口
6.1, test方法 ?
Predicate?接口中包含一個(gè)抽象方法:?boolean test(T t)?。用于條件判斷的場(chǎng)景
1. public enum SingleClass06 { ?
2. ????INSTANCE; ?
3. }
6.2,基本使用
1. public static void main(String[] args) { ?
2. ????System.out.println(predicateTest((msg) -> msg.length() > 3, "hello")); ?
3. } ?
4. ??
5. ??
6. public static boolean predicateTest(Predicate<String> predicate,String msg){ ?
7. ????return predicate.test(msg); ?
8. ?????
9. }
7.總結(jié)
在本文中,我們學(xué)會(huì)了使用lambda表達(dá)式的不同方式,同時(shí)也學(xué)習(xí)了java8.0開始自帶的一些常用函數(shù)式接口。
文章名稱:好程序員Java教程分享Java8.0新特性之Lambda表達(dá)式
瀏覽地址:http://www.rwnh.cn/article46/jgjchg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站建設(shè)、網(wǎng)站維護(hù)、Google、網(wǎng)站導(dǎo)航、App開發(fā)、微信公眾號(hào)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)