JDK新特性-Lambda表示式的神操作

itread01 2020-11-07 16:46:47
jdk Lambda 操作 表示 特性


## 一、Lambda表示式的介紹 - Lambda表示式是 Java8 中最重要的新功能之一。使用 Lambda 表達 式可以替代只有一個抽象函式的介面實現,告別匿名內部類,程式碼看 起來更簡潔易懂。Lambda表示式同時還提升了對集合、框架的迭代、 遍歷、過濾資料的操作。 - lambda表示式可以替代只有一個抽象函式的介面實現,告別匿名內部類,程式碼看起來更簡潔易懂 - lambda表示式同時還提升了對集合、框架的迭代、遍歷、過濾資料的操作 - lambda可以極大的減少程式碼冗餘,同時代碼的可讀性要好過冗長的內部類,匿名類 例如以前我們使用匿名內部類來實現程式碼: ```java Runnable runnable = new Runnable() { @Override public void run() { System.out.println("running1 ....."); } }; runnable.run(); ``` 使用lambda表示式實現更簡潔的程式碼: ```java Runnable runnable3 = ()-> System.out.println("running2...."); runnable3.run(); ``` **lambda表示式語法:** ```java LambdaParameters -> LambdaBody ``` ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20201107094149930.png#pic_center) args -> expr或者(object ... args)-> {函式式介面抽象方法實現邏輯} ​ 1、()引數的個數,根據函式式接口裡面抽象的引數個數來決定,當引數只有一個的時候,()可以省略 ​ 2、當expr邏輯非常簡單的時候,{}和return可以省略 **案例說明:** ```java public static void main(String[] args) throws Exception { Callable c1 = new Callable() { @Override public String call() throws Exception { return "muxiaonong"; } }; System.out.println(c1.call()); Callable c2 = ()->{return "muxiaonong2";}; System.out.println(c2.call()); //邏輯很簡單的時候省略 {} 和 return Callable c3 = ()->"muxiaonong3"; System.out.println(c3.call()); } ``` ## 二、Lambda表示式的特點 - 函數語言程式設計 - 引數型別自動推斷 - 程式碼量少,簡潔 ## 三、Lambda表示式案例 **實現方式列表:** ```java ​ ()->{} ​ ()->{System.out.println(1);} ​ ()->System.out.println(1) ​ ()->{return 100;} ​ ()->100 ​ ()->null ​ (int x)->{return x+1;} ​ (int x)->x+1 ​ (x)->x+1 ​ x->x+1 ``` 案例1:執行緒實現方式: ```java public static void main(String[] args) { //匿名內部類方式 new Thread(new Runnable() { @Override public void run() { System.out.println("runing1.........."); } }); //Lambda表示式方式 new Thread(() -> {System.out.println("runing2.....");}).start(); } ``` 案例2:集合遍歷實現方式 ```java public static void main(String[] args) { List list = Arrays.asList("java","python","scala","javascript"); //普通匿名內部類方式 Collections.sort(list, new Comparator () { @Override public int compare(String o1, String o2) { return o1.length() - o2.length(); } }); //Lambda方式 Collections.sort(list,(a,b) -> a.length() - b.length()); list.forEach(System.out::println); } ``` ## 四、Lambda表示式的應用場景 重要的事情說三遍:**任何有函式式介面的地方 * 3** **什麼是函式式介面:** ```只有一個抽象方法(Object類中的方法除外)的介面是函式式介面``` ## 五、Lambda表示式實際應用 #### 5.1 無參實體類模擬 **模擬資料庫連線層:** ```java @FunctionalInterface public interface StudentDao { void insert(Student student); } ``` 實體類 ```java /** @Author mxn * @Description 學生實體類 * @Date 10:19 2020/11/7 * @Param * @return **/ public class Student { } ``` ```java public static void main(String[] args) { StudentDao sd1 = new StudentDao() { @Override public void insert(Student student) { System.out.println("插入學生1"); } }; StudentDao sd2 = (student)->{ System.out.println("student: "+student); }; StudentDao sd3 = (Student student)-> System.out.println("student3:"+student); sd1.insert(new Student()); //輸出 插入學生1 sd2.insert(new Student());// 輸出 sd3.insert(new Student());// 輸出 } ``` #### 5.2 有參實體類模擬 實體類 ```java /** @Author mxn * @Description * @Date 10:26 2020/11/7 * @Param * @return **/ public class Teacher { } ``` 介面模擬層 ```java @FunctionalInterface public interface TeacherDao { int get(Teacher teacher); } ``` 實現層 ```java public static void main(String[] args) { TeacherDao td1 = new TeacherDao() { @Override public int get(Teacher teacher) { return 1; } }; TeacherDao td2 = (teacher)->{return 2;}; TeacherDao td3 = (Teacher teacher)->{return 3;}; TeacherDao td4 = (teacher)->4; TeacherDao td5 = (Teacher teacher)->5; System.out.println(td1.get(new Teacher()));//輸出 1 System.out.println(td2.get(new Teacher()));//輸出 2 System.out.println(td3.get(new Teacher()));//輸出 3 System.out.println(td4.get(new Teacher()));//輸出 4 System.out.println(td5.get(new Teacher()));//輸出 5 } ``` ## 六、函式式介面 ```Supplier:```代表一個輸出 ```Consumer:```代表一個輸入 ```BiConsumer:```代表兩個輸入 ```Function:```代表一個輸入,一個輸出(一般輸入和輸出是不同型別的) ```UnaryOperator:```代表一個輸入,一個輸出(輸入和輸出是相同型別的) ```BiFunction:```代表兩個輸入,一個輸出(一般輸入和輸出是不同型別的) ```BinaryOperator:```代表兩個輸入,一個輸出(輸入和輸出是相同型別的) **在Java中提供了一系列的函式式介面,用來接受後續傳入的邏輯,但是對輸入和輸出有要求** #### 6.1 Supplier:代表一個輸出 ```java Supplier s1 = ()->{return "muxiaonong";}; Supplier s2 = ()->"muxiaonong2"; System.out.println(s1.get());//輸出 muxiaonong System.out.println(s2.get());//輸出 muxiaonong2 ``` #### 6.2 Consumer:代表一個輸入 ```java Consumer c11 = (str) -> System.out.println(str); c11.accept("beijing");//輸出 beijing ``` #### 6.3 BiConsumer:代表兩個輸入 ```java BiFunction bf = (a,b)->a.length()+b.length(); System.out.println(bf.apply("大吉大利", "今晚吃雞"));//輸出一個字串長度 8 ``` #### 6.4 Function:代表一個輸入,一個輸出 ```java // Function 用來接收後面的函式的實現,規定必須有一個輸入(String)有一個輸出(Integer) Function f1 = (str)->{return str.length();}; System.out.println(f1.apply("abcdefg"));//輸出長度 7 ``` ## 七、方法的引用 - 方法引用是用來直接訪問類或者例項的已經存在的方法或者構造方法,方法引用提供了一種引用而不執行方法的方式,如果抽象方法的實現恰好可以使用呼叫另外一個方法來實現,就有可能可以使用方法引用 #### 7.1 方法引用的分類 型別| 語法| 對應的lambda表示式 -------- | ----- | ----- 靜態方法引用| 類名::staticMethod | (args) -> 類名.staticMethod(args) 例項方法引用 | inst::instMethod| (args) -> inst.instMethod(args) 物件方法引用| 類名::instMethod| (inst,args) -> 類名.instMethod(args) 構造方法引用| 類名::new| (args) -> new 類名(args) #### 7.2 靜態方法引用 - **靜態方法引用:** 如果函式式介面的實現恰好可以通過 **呼叫一個靜態方法** 來實現,那麼就可以使用靜態方法引用 ```java /** * @program: lambda * @ClassName Test2 * @description: * @author: muxiaonong * @create: 2020-10-28 22:15 * @Version 1.0 **/ public class Test2 { //無參靜態方法 static String put(){ System.out.println("put....."); return "put"; } //有參靜態方法 public static void getSize(int size){ System.out.println(size); } //有參 有返回值靜態方法 public static String toUpperCase(String str){ return str.toUpperCase(); } //兩個入參,一個返回值靜態方法 public static Integer getLength(String str,String str2){ return str.length()+str2.length(); } public static void main(String[] args) { //無參靜態方法-普通呼叫 System.out.println(put());//輸出put //無參靜態方法-原生呼叫 Supplier s1 = ()-> Test2.put(); System.out.println(s1.get());//輸出put //無參靜態方法-靜態方法引用 Supplier s2 = Test2::put; System.out.println(s2.get());//輸出put //無參靜態方法-內部類呼叫 Supplier s3 = Fun::hehe; System.out.println(s3.get()); //輸出hehe // 有參靜態方法-靜態方法引用 Consumer c1 = Test2::getSize; Consumer c2 = (size)-> Test2.getSize(size); c1.accept(123); c2.accept(111); //有參有返回值靜態方法 Function f1 = (str)->str.toUpperCase(); Function f2 = (str)-> Test2.toUpperCase(str); Function f3 = Test2::toUpperCase; Function f4 = Test2::toUpperCase; System.out.println(f1.apply("abc"));//輸出 ABC System.out.println(f2.apply("abc"));//輸出 ABC System.out.println(f3.apply("abc"));//輸出 ABC System.out.println(f4.apply("abc"));//輸出 ABC // 兩個引數 一個返回值 函式式介面 BiFunction bf = (a, b)->a.length()+b.length(); BiFunction bf2 = Test2::getLength; System.out.println(bf2.apply("abc", "def"));//輸出 6 System.out.println(bf.apply("abc", "def"));//輸出 6 } //內部類 class Fun { public static String hehe(){ return "hehe"; } public static String toUpperCase(String str){ return str.toUpperCase(); } } } ``` #### 7.3 例項方法引用 - **例項方法引用:** 如果函式式介面的實現恰好可以通過呼叫一個例項的例項方法來實現,那麼就可以使用例項方法引用 ```java public class Test3 { //例項無參方法 public String put(){ return "put..."; } //例項有參方法 public void getSize(int size){ System.out.println("size:"+size); } //例項有參有返回值方法 public String toUpperCase(String str){ return str.toUpperCase(); } public static void main(String[] args) { //例項無參方法返回-普通呼叫 System.out.println(new Test3().put());//輸出 put... Supplier s1 = ()->new Test3().put(); Supplier s2 = ()->{return new Test3().put();}; Supplier s3 = new Test3()::put; System.out.println(s1.get());//輸出 put... System.out.println(s2.get());//輸出 put... System.out.println(s3.get());//輸出 put... //唯一的建立一個test3物件 Test3 test = new Test3(); Consumer c1 = (size)->new Test3().getSize(size); Consumer c2 = new Test3()::getSize; Consumer c3 = test::getSize; c1.accept(123);//輸出 size:123 c2.accept(123);//輸出 size:123 c3.accept(123);//輸出 size:123 Function f1 = (str)->str.toUpperCase(); Function f2 = (str)->test.toUpperCase(str); Function f3 = new Test3()::toUpperCase; Function f4 = test::toUpperCase; System.out.println(f1.apply("abc"));//輸出 ABC System.out.println(f2.apply("abc"));//輸出 ABC System.out.println(f3.apply("abc"));//輸出 ABC System.out.println(f4.apply("abc"));//輸出 ABC } } ``` #### 7.4 物件方法引用 - **物件方法引用:** 抽象方法的第一個引數型別剛好是例項方法的型別,抽象方法剩餘的引數恰好可以當做例項方法的引數。如果函式式介面的實現能由上面說的例項方法呼叫來實現的話,那麼就可以使用物件方法引用 ```java /** @Author mxn * @Description //TODO 物件方法引用 * @Date 14:26 2020/11/7 * @Param * @return **/ public class Test4 { public static void main(String[] args) { Consumer c1 = (too)->new Too().foo(); c1.accept(new Too());//輸出 foo Consumer c2 = (Too too) ->new Too2().foo(); c2.accept(new Too());//輸出 foo---too2 Consumer c3 = Too::foo; c3.accept(new Too());//輸出 foo BiConsumer bc = (too2,str)->new Too2().show(str); BiConsumer bc2 = Too2::show; bc.accept(new Too2(),"abc"); bc2.accept(new Too2(),"def"); BiFunction bf1 = (e,s)->new Exec().test(s); bf1.apply(new Exec(),"abc"); BiFunction bf2 = Exec::test; bf2.apply(new Exec(),"def"); } } class Exec{ public int test(String name){ return 1; } } class Too{ public Integer fun(String s){ return 1; } public void foo(){ System.out.println("foo"); } } class Too2{ public Integer fun(String s){ return 1; } public void foo(){ System.out.println("foo---too2"); } public void show(String str){ System.out.println("show ---too2"+str); } } ``` #### 7.5 構造方法引用 - **構造方法引用:** 如果函式式介面的實現恰好可以通過呼叫一個類的構造方法來實現,那麼就可以使用構造方法引用 ```java /** @Author mxn * @Description //TODO 構造方法引用 * @Date 14:27 2020/11/7 * @Param * @return **/ public class Test5 { public static void main(String[] args) { Supplier s1 = ()->new Person(); s1.get();//輸出 呼叫無參的構造方法 Supplier s2 = Person::new; s2.get();//輸出 呼叫無參的構造方法 Supplier s3 = ArrayList::new; Supplier s4 = HashSet::new; Supplier s5 = Thread::new; Supplier s6 = String::new; Consumer c1 = (age)->new Account(age); Consumer c2 = Account::new; c1.accept(123);// 輸出 age 引數構造123 c2.accept(456);//輸出 age 引數構造456 Function f1 = (str)->new Account(str); Function f2 = Account::new; f1.apply("abc");//輸出 str 引數構造abc f2.apply("def");//輸出 str 引數構造def } } class Account{ public Account(){ System.out.println("呼叫無參構造方法"); } public Account(int age){ System.out.println("age 引數構造" +age); } public Account(String str){ System.out.println("str 引數構造" +str); } } class Person{ public Person(){ System.out.println("呼叫無參的構造方法"); } } ``` ## 八、小結 - JAVA 8 引入 Lambda表示式是接收了函數語言程式設計語言的思想,和指令式程式設計相比,函數語言程式設計強調函式的計算比指令的執行重要。 - lambda表示式可以使程式碼看起來簡潔,但一定程度上增加了程式碼的可讀性以及除錯的複雜性,所以在使用時應儘量是團隊都熟悉使用,要麼乾脆就別用,不然維護起來是件較痛苦的事,今天的小知識就到這裡了,有問題的小夥伴可以在下方進行留言,大家
版权声明
本文为[itread01]所创,转载请带上原文链接,感谢
https://www.itread01.com/content/1604736482.html

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云