深圳Java培訓學習:Java8.0新特性之Lambda表示式
深圳Java 培訓學習: Java8.0 新特性之 Lambda 表示式
前言
Java 8 已經發布很久了,很多報導表明 Java 8 是一次重大的版本升級。本篇文章,主要給大家介紹的是 lambda 表示式。
Lambda 表示式
Lambda 表示式(也稱為閉包)是 Java 8 中最大和最令人期待的語言改變。它允許我們將函式當成引數傳遞給某個方法,或者把程式碼本身當作資料處理:函式式開發者非常熟悉這些概念。
很多JVM 平臺上的語言( Groovy 、 Scala 等)從誕生之日就支援 Lambda 表示式,但是 Java 開發者沒有選擇,只能使用匿名內部類代替 Lambda 表示式。
Lambda 的設計耗費了很多時間和很大的社群力量,最終找到一種折中的實現方案,可以實現簡潔而緊湊的語言結構。而 lambda 表示式的使用需要和函式式介面結合。
1. 函式式介面
1.1. 概念
函式式介面在Java 中是指:有且僅有一個抽象方法的介面。 函式式介面,即適用於函數語言程式設計場景的介面。而 Java 中的函數語言程式設計體現就是 Lambda ,所以函式式介面就是可 以適用於 Lambda 使用的介面。只有確保介面中有且僅有一個抽象方法, Java 中的 Lambda 才能順利地進行推導。 備註:“語法糖”是指使用更加方便,但是原理不變的程式碼語法。例如在遍歷集合時使用的 for-each 語法,其實 底層的實現原理仍然是迭代器,這便是“語法糖”。從應用層面來講, Java 中的 Lambda 可以被當做是匿名內部 類的“語法糖”,但是二者在原理上是不同的。
1.2, 格式
只要確保介面中有且僅有一個抽象方法即可:
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 開始自帶的一些常用函式式介面。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69947096/viewspace-2661698/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 好程式設計師Java教程分享Java8.0新特性之Lambda表示式程式設計師Java
- java8 新特性之Lambda 表示式Java
- Java8 新特性之 Lambda 表示式Java
- java8新特性之lambda表示式(一)Java
- [Java學習筆記]JDK1.8新特性學習(一)Lambda表示式Java筆記JDK
- java 8新特性學習之五:Java 8 lambda表示式初步第五回Java
- java 8新特性學習之四:Java 8 lambda表示式初步第四回Java
- Java 8新特性(一):Lambda表示式Java
- JDK 1.8 新特性之Lambda表示式JDK
- Java8新特性(1):Lambda表示式Java
- Java8新特性(一)-Lambda表示式Java
- java-反射,介面新特性,Lambda表示式Java反射
- JDK1.8新特性之Lambda表示式JDK
- JDK1.8新特性之Lambda表示式()->JDK
- jdk1.8 新特性之 lambda表示式JDK
- C++11新特性之Lambda表示式C++
- java8的新特性之lambda表示式和方法引用Java
- JDK1.8的新特性之Lambda表示式JDK
- java 8新特性學習之三:Java 8 lambda表示式初步第三回Java
- Java 8新特性學習之一:Java 8 lambda表示式初步第六回Java
- java 8新特性學習之二:Java 8 lambda表示式初步第二回Java
- Java 8新特性學習之一:Java 8 lambda表示式初步第一回Java
- Java8新特性第1章(Lambda表示式)Java
- jdk1.8 新特性之 如何寫lambda表示式JDK
- Java Lambda 表示式學習筆記Java筆記
- java8特性-lambda表示式Java
- Java之lambda表示式Java
- JDK1.8新特性--Lambda表示式JDK
- jdk1.8新特性:Lambda表示式JDK
- .NET3.5新特性,Lambda表示式
- 好程式設計師分享java8新特性之Lambda表示式程式設計師Java
- Java8新特性——從Lambda表示式到Stream流Java
- Java 8新特性:lambda表示式(四)轉載總結Java
- java8學習:lambda表示式(2)Java
- java8學習:lambda表示式(1)Java
- Java 8 流特性和 Lambda 表示式Java
- JDK新特性-Lambda表示式的神操作JDK
- .net framework3.5新特性:Lambda表示式Framework