好程序員Java教程分享Java8.0新特性之Lambda表達式:Java 8?已經(jīng)發(fā)布很久了,很多報道表明Java 8?是一次重大的版本升級。本篇文章,主要給大家介紹的是lambda表達式。
創(chuàng)新互聯(lián)擁有網(wǎng)站維護技術和項目管理團隊,建立的售前、實施和售后服務體系,為客戶提供定制化的成都網(wǎng)站制作、網(wǎng)站設計、網(wǎng)站維護、服務器托管解決方案。為客戶網(wǎng)站安全和日常運維提供整體管家式外包優(yōu)質(zhì)服務。我們的網(wǎng)站維護服務覆蓋集團企業(yè)、上市公司、外企網(wǎng)站、商城網(wǎng)站定制開發(fā)、政府網(wǎng)站等各類型客戶群體,為全球1000多家企業(yè)提供全方位網(wǎng)站維護、服務器維護解決方案。
Lambda表達式
Lambda表達式(也稱為閉包)是Java 8中最大和最令人期待的語言改變。它允許我們將函數(shù)當成參數(shù)傳遞給某個方法,或者把代碼本身當作數(shù)據(jù)處理:函數(shù)式開發(fā)者非常熟悉這些概念。
很多JVM平臺上的語言(Groovy、Scala等)從誕生之日就支持Lambda表達式,但是Java開發(fā)者沒有選擇,只能使用匿名內(nèi)部類代替Lambda表達式。
Lambda的設計耗費了很多時間和很大的社區(qū)力量,最終找到一種折中的實現(xiàn)方案,可以實現(xiàn)簡潔而緊湊的語言結(jié)構(gòu)。而lambda表達式的使用需要和函數(shù)式接口結(jié)合。
1.函數(shù)式接口
1.1.概念
函數(shù)式接口在Java中是指:有且僅有一個抽象方法的接口。 函數(shù)式接口,即適用于函數(shù)式編程場景的接口。而Java中的函數(shù)式編程體現(xiàn)就是Lambda,所以函數(shù)式接口就是可 以適用于Lambda使用的接口。只有確保接口中有且僅有一個抽象方法,Java中的Lambda才能順利地進行推導。 備注:“語法糖”是指使用更加方便,但是原理不變的代碼語法。例如在遍歷集合時使用的for-each語法,其實 底層的實現(xiàn)原理仍然是迭代器,這便是“語法糖”。從應用層面來講,Java中的Lambda可以被當做是匿名內(nèi)部 類的“語法糖”,但是二者在原理上是不同的。
1.2,格式
只要確保接口中有且僅有一個抽象方法即可:
1.?修飾符?interface?接口名稱?{ ??????????
2. ????public abstract?返回值類型 方法名稱(可選參數(shù)信息); ?
3. } ?
1.3 @FunctionalInterface注解
與?@Override?注解的作用類似,Java 8中專門為函數(shù)式接口引入了一個新的注解:?@FunctionalInterface?。該注解可用于一個接口的定義上:
1. @FunctionalInterface ?
2. public interface MyFunctionalInterface { ?
3. ????void myMethod(); ?
4. }
一旦使用該注解來定義接口,編譯器將會強制檢查該接口是否確實有且僅有一個抽象方法,否則將會報錯。需要注?意的是,即使不使用該注解,只要滿足函數(shù)式接口的定義,這仍然是一個函數(shù)式接口,使用起來都一樣.
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)部類對象/函數(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ù)式簡寫(如果方法體中只有一句代碼) ?
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ù)式接口比匿名內(nèi)部類對象產(chǎn)生更少的字節(jié)碼對象,提升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)部類對象 ?
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ù)式簡寫 ?
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ù)式簡寫 ?
23. public static MyInterface02 getInter2() { ?
24. ??
25. ????return (msg1, msg2) -> System.out.println(msg1 + msg2); ?
26. } ?
3.函數(shù)式編程應用場景
3.1,概念
在兼顧面向?qū)ο筇匦缘幕A上,Java語言通過Lambda表達式使用函數(shù)式接口,就叫做函數(shù)式編程
3.2,?使用lambada作為參數(shù)
如果拋開實現(xiàn)原理不說,Java中的Lambda表達式可以被當作是匿名內(nèi)部類的替代品。如果方法的參數(shù)是一個函數(shù) 式接口類型,那么就可以使用Lambda表達式進行替代。
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ù)式接口作為返回值
如果一個方法的返回值類型是一個函數(shù)式接口,那么就可以直接返回一個Lambda表達式。
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表達式 ?
12. ????????showMsg(() -> { ?
13. ??
14. ????????????return "hello1 functional interface"; ?
15. ????????}); ?
16. ??
17. ????????// lambda表達式簡寫 ?
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的典型使用場景,它們主要在?java.util.function?包中被提供。 下面是簡單的幾個接口及使用示例。
4.1,Supplier接口 ?
java.util.function.Supplier<T>?接口僅包含一個無參的方法:?T get()?。用來獲取一個泛型參數(shù)指定類型的對象數(shù)據(jù)。由于這是一個函數(shù)式接口,這也就意味著對應的Lambda表達式需要“對外提供”一個符合泛型類型的對象數(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ù)類型,通過Lambda表達式求出int數(shù)組中的最大值。提示:接口的泛型請使用?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)一個數(shù)據(jù),而是消費一個數(shù)據(jù), 其數(shù)據(jù)類型由泛型決定
5.2,accept方法 ??
Consumer?接口中包含抽象方法?void accept(T t)?,意為消費一個指定泛型的數(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方法 ??
如果一個方法的參數(shù)和返回值全都是?Consumer?類型,那么就可以實現(xiàn)效果:消費數(shù)據(jù)的時候,首先做一個操作, 然后再做一個操作,實現(xiàn)組合。而這個方法就是?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)方法將會在參數(shù)為null時主動拋出?NullPointerException?異常。這省去了重復編寫if語句和拋出空指針異常的麻煩。
需求:先打印大寫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ù)據(jù)進行判斷,從而得到一個boolean值結(jié)果。這時可以使用?java.util.function.Predicate<T>?接口
6.1, test方法 ?
Predicate?接口中包含一個抽象方法:?boolean test(T t)?。用于條件判斷的場景
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é)
在本文中,我們學會了使用lambda表達式的不同方式,同時也學習了java8.0開始自帶的一些常用函數(shù)式接口。
文章名稱:好程序員Java教程分享Java8.0新特性之Lambda表達式
瀏覽地址:http://chinadenli.net/article46/jgjchg.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站建設、網(wǎng)站維護、Google、網(wǎng)站導航、App開發(fā)、微信公眾號
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)