溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

好程序員Java教程分享Java8.0新特性之Lambda表達式

發(fā)布時間:2020-07-30 21:13:57 來源:網(wǎng)絡(luò) 閱讀:131 作者:wx5da18b5c4b01e 欄目:編程語言

  好程序員Java教程分享Java8.0新特性之Lambda表達式:Java 8?已經(jīng)發(fā)布很久了,很多報道表明Java 8?是一次重大的版本升級。本篇文章,主要給大家介紹的是lambda表達式。

Lambda表達式

Lambda表達式(也稱為閉包)是Java 8中最大和最令人期待的語言改變。它允許我們將函數(shù)當(dāng)成參數(shù)傳遞給某個方法,或者把代碼本身當(dāng)作數(shù)據(jù)處理:函數(shù)式開發(fā)者非常熟悉這些概念。

很多JVM平臺上的語言(Groovy、Scala等)從誕生之日就支持Lambda表達式,但是Java開發(fā)者沒有選擇,只能使用匿名內(nèi)部類代替Lambda表達式。

Lambda的設(shè)計耗費了很多時間和很大的社區(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才能順利地進行推導(dǎo)。 備注:“語法糖”是指使用更加方便,但是原理不變的代碼語法。例如在遍歷集合時使用的for-each語法,其實 底層的實現(xiàn)原理仍然是迭代器,這便是“語法糖”。從應(yīng)用層面來講,Java中的Lambda可以被當(dāng)做是匿名內(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ù)式編程應(yīng)用場景

3.1,概念

在兼顧面向?qū)ο筇匦缘幕A(chǔ)上,Java語言通過Lambda表達式使用函數(shù)式接口,就叫做函數(shù)式編程

3.2,?使用lambada作為參數(shù)

如果拋開實現(xiàn)原理不說,Java中的Lambda表達式可以被當(dāng)作是匿名內(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ù)式接口,這也就意味著對應(yīng)的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?異常。這省去了重復(fù)編寫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é)

在本文中,我們學(xué)會了使用lambda表達式的不同方式,同時也學(xué)習(xí)了java8.0開始自帶的一些常用函數(shù)式接口。


向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI