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

  好程序員Java教程分享Java8.0新特性之Lambda表達式:Java 8 已經發布好久了,不少報道代表Java 8 是一次重大的版本升級。本篇文章,主要給你們介紹的是lambda表達式。java

Lambda表達式程序員

Lambda表達式(也稱爲閉包)是Java 8中最大和最使人期待的語言改變。它容許咱們將函數當成參數傳遞給某個方法,或者把代碼自己看成數據處理:函數式開發者很是熟悉這些概念。編程

不少JVM平臺上的語言(GroovyScala等)從誕生之日就支持Lambda表達式,可是Java開發者沒有選擇,只能使用匿名內部類代替Lambda表達式。數組

Lambda的設計耗費了不少時間和很大的社區力量,最終找到一種折中的實現方案,能夠實現簡潔而緊湊的語言結構。而lambda表達式的使用須要和函數式接口結合。閉包

1.函數式接口ide

1.1.概念函數式編程

函數式接口在Java中是指:有且僅有一個抽象方法的接口。 函數式接口,即適用於函數式編程場景的接口。而Java中的函數式編程體現就是Lambda,因此函數式接口就是可 以適用於Lambda使用的接口。只有確保接口中有且僅有一個抽象方法,Java中的Lambda才能順利地進行推導。 備註:「語法糖」是指使用更加方便,可是原理不變的代碼語法。例如在遍歷集合時使用的for-each語法,其實 底層的實現原理仍然是迭代器,這即是「語法糖」。從應用層面來說,Java中的Lambda能夠被當作是匿名內部 類的「語法糖」,可是兩者在原理上是不一樣的。函數

1.2,格式學習

只要確保接口中有且僅有一個抽象方法便可:ui

1. 修飾符 interface 接口名稱 {           

2.     public abstract 返回值類型 方法名稱(可選參數信息);  

3. }  

1.3 @FunctionalInterface註解

 @Override 註解的做用相似,Java 8中專門爲函數式接口引入了一個新的註解: @FunctionalInterface 。該註解可用於一個接口的定義上:

1. @FunctionalInterface  

2. public interface MyFunctionalInterface {  

3.     void myMethod();  

4. }

一旦使用該註解來定義接口,編譯器將會強制檢查該接口是否確實有且僅有一個抽象方法,不然將會報錯。須要注 意的是,即便不使用該註解,只要知足函數式接口的定義,這仍然是一個函數式接口,使用起來都同樣.

2.函數式接口的使用

2.1函數式接口做爲參數,方法不帶參數

1. //定義函數式接口  

2. public interface MyInterface{  

3.      

4.     public abstract void show();  

5.      

6. }  

7.   

8. //使用(匿名內部類對象/函數式)   

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("你好,函數式接口");  

17.             }  

18.         });  

19.         // 函數式  

20.         method01(() -> {  

21.             System.out.println("你好,函數式接口");  

22.         });  

23.         // 函數式簡寫(若是方法體中只有一句代碼)  

24.         method01(() -> System.out.println("你好,函數式接口"));  

25.     }  

26.   

27.     public static void method01(MyInterface01 inter) {  

28.         inter.show();  

29.     }  

30.   

31. }

函數式接口的優點

函數式接口比匿名內部類對象產生更少的字節碼對象,提高java執行效率.

2.2, 函數式接口做爲參數,方法帶參數

1. //定義函數式接口  

2.     public interface MyInterface02 {  

3.   

4.         public abstract void show(String msg1, String msg2);  

5.   

6.     }  

7.   

8.     //使用函數式接口  

9.     public static void main(String[] args) {  

10.         //匿名內部類對象  

11.         method01(new MyInterface02() {  

12.   

13.             @Override  

14.             public void show(String msg1, String msg2) {  

15.                 System.out.println(msg1 + msg2);  

16.             }  

17.         });  

18.         //函數式完整  

19.         method01((String msg1, String msg2) -> {  

20.             System.out.println(msg1 + msg2);  

21.         });  

22.         //函數式簡寫  

23.         method01((msg1, msg2) -> System.out.println(msg1 + msg2));  

24.   

25.     }  

26.   

27.     public static void method01(MyInterface02 inter) {  

28.         inter.show("hello", "函數式");  

29.     }

2.3, 函數式接口做爲返回值,方法不帶參數

1.    //定義函數式接口  

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("你好", "函數式");  

10.     getInter2().show("你好", "函數式");  

11.   

12. }  

13.   

14. // 函數式完整  

15. public static MyInterface02 getInter1() {  

16.   

17.     return (String msg1, String msg2) -> {  

18.         System.out.println(msg1 + msg2);  

19.     };  

20. }  

21.   

22. // 函數式簡寫  

23. public static MyInterface02 getInter2() {  

24.   

25.     return (msg1, msg2) -> System.out.println(msg1 + msg2);  

26. }  

3.函數式編程應用場景

3.1,概念

在兼顧面向對象特性的基礎上,Java語言經過Lambda表達式使用函數式接口,就叫作函數式編程

3.2, 使用lambada做爲參數

若是拋開實現原理不說,Java中的Lambda表達式能夠被看成是匿名內部類的替代品。若是方法的參數是一個函數 式接口類型,那麼就可使用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("線程執行"));   

7.     }   

8. }  

3.3, 使用函數式接口做爲返回值

若是一個方法的返回值類型是一個函數式接口,那麼就能夠直接返回一個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.         //遍歷數組  

11.     }   

12. }

3.4, 函數式接口的方法有返回值

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.經常使用函數式接口(Supplier接口)

JDK提供了大量經常使用的函數式接口以豐富Lambda的典型使用場景,它們主要在 java.util.function 包中被提供。 下面是簡單的幾個接口及使用示例。

4.1,Supplier接口  

java.util.function.Supplier<T> 接口僅包含一個無參的方法: T get() 。用來獲取一個泛型參數指定類型的對象數據。因爲這是一個函數式接口,這也就意味着對應的Lambda表達式須要「對外提供」一個符合泛型類型的對象數據

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 接口做爲方法參數類型,經過Lambda表達式求出int數組中的最大值。提示:接口的泛型請使用 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.經常使用函數式接口(Consumer接口)

5.1,Consumer接口  

java.util.function.Consumer<T> 接口則正好與Supplier接口相反,它不是生產一個數據,而是消費一個數據, 其數據類型由泛型決定

5.2,accept方法   

Consumer 接口中包含抽象方法 void accept(T t) ,意爲消費一個指定泛型的數據。基本使用如:

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方法   

若是一個方法的參數和返回值全都是 Consumer 類型,那麼就能夠實現效果:消費數據的時候,首先作一個操做, 而後再作一個操做,實現組合。而這個方法就是 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 靜態方法將會在參數爲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.經常使用函數式接口(Predicate接口)

有時候咱們須要對某種類型的數據進行判斷,從而獲得一個boolean值結果。這時可使用 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.總結

在本文中,咱們學會了使用lambda表達式的不一樣方式,同時也學習了java8.0開始自帶的一些經常使用函數式接口。

相關文章
相關標籤/搜索