文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2024-12-03 06:05

关注

一、Lambda表达式的介绍

例如以前我们使用匿名内部类来实现代码:

  1. Runnable runnable = new Runnable() { 
  2.        @Override 
  3.        public void run() { 
  4.            System.out.println("running1 ....."); 
  5.        } 
  6.    }; 
  7.    runnable.run(); 

使用lambda表达式实现更简洁的代码:

  1. Runnable runnable3 = ()-> System.out.println("running2...."); 
  2.     runnable3.run(); 

lambda表达式语法:

  1. LambdaParameters -> LambdaBody 

 

在这里插入图片描述

args -> expr或者(object … args)-> {函数式接口抽象方法实现逻辑}

()参数的个数,根据函数式接口里面抽象的参数个数来决定,当参数只有一个的时候,()可以省略

当expr逻辑非常简单的时候,{}和return可以省略

案例说明:

  1. public static void main(String[] args) throws Exception { 
  2.       Callable c1 = new Callable() { 
  3.           @Override 
  4.           public String call() throws Exception { 
  5.               return "muxiaonong"
  6.           } 
  7.       }; 
  8.       System.out.println(c1.call()); 
  9.  
  10.       Callable c2 = ()->{return "muxiaonong2";}; 
  11.       System.out.println(c2.call()); 
  12.  
  13.       //逻辑很简单的时候省略 {} 和 return 
  14.       Callable c3 = ()->"muxiaonong3"
  15.       System.out.println(c3.call()); 
  16.   } 

二、Lambda表达式的特点

三、Lambda表达式案例

实现方式列表:

  1. ()->{} 
  2.        ()->{System.out.println(1);} 
  3.        ()->System.out.println(1) 
  4.        ()->{return 100;} 
  5.        ()->100 
  6.        ()->null 
  7.        (int x)->{return x+1;} 
  8.        (int x)->x+1 
  9.        (x)->x+1 
  10.        x->x+1 

案例1:线程实现方式:

  1. public static void main(String[] args) { 
  2.       //匿名内部类方式 
  3.       new Thread(new Runnable() { 
  4.           @Override 
  5.           public void run() { 
  6.               System.out.println("runing1.........."); 
  7.           } 
  8.       }); 
  9.  
  10.       //Lambda表达式方式 
  11.       new Thread(() -> {System.out.println("runing2.....");}).start(); 
  12.   } 

案例2:集合遍历实现方式

  1. public static void main(String[] args) { 
  2.       List list = Arrays.asList("java","python","scala","javascript"); 
  3.  
  4.       //普通匿名内部类方式 
  5.       Collections.sort(list, new Comparator() { 
  6.           @Override 
  7.           public int compare(String o1, String o2) { 
  8.               return o1.length() - o2.length(); 
  9.           } 
  10.       }); 
  11.  
  12.       //Lambda方式 
  13.       Collections.sort(list,(a,b) -> a.length() - b.length()); 
  14.       list.forEach(System.out::println); 
  15.   } 

四、Lambda表达式的应用场景

重要的事情说三遍:任何有函数式接口的地方 * 3

什么是函数式接口: 只有一个抽象方法(Object类中的方法除外)的接口是函数式接口

五、Lambda表达式实际应用

1 无参实体类模拟

模拟数据库连接层:

  1. @FunctionalInterface 
  2. public interface StudentDao { 
  3.     void insert(Student student); 

实体类

  1.  
  2. public class Student { 
  3.  public static void main(String[] args) { 
  4.         StudentDao sd1 = new StudentDao() { 
  5.             @Override 
  6.             public void insert(Student student) { 
  7.                 System.out.println("插入学生1"); 
  8.             } 
  9.         }; 
  10.  
  11.         StudentDao sd2 = (student)->{ 
  12.             System.out.println("student: "+student); 
  13.         }; 
  14.  
  15.         StudentDao sd3 = (Student student)-> System.out.println("student3:"+student); 
  16.  
  17.         sd1.insert(new Student()); //输出 插入学生1 
  18.         sd2.insert(new Student());// 输出 
  19.         sd3.insert(new Student());// 输出 
  20.     } 

 5.2 有参实体类模拟

实体类

  1.  
  2. public class Teacher { 

接口模拟层

  1. @FunctionalInterface 
  2. public interface TeacherDao { 
  3.     int get(Teacher teacher); 

实现层

  1.  public static void main(String[] args) { 
  2.         TeacherDao td1 = new TeacherDao() { 
  3.             @Override 
  4.             public int get(Teacher teacher) { 
  5.                 return 1; 
  6.             } 
  7.         }; 
  8.         TeacherDao td2 = (teacher)->{return 2;}; 
  9.         TeacherDao td3 = (Teacher teacher)->{return 3;}; 
  10.         TeacherDao td4 = (teacher)->4; 
  11.         TeacherDao td5 = (Teacher teacher)->5; 
  12.  
  13.         System.out.println(td1.get(new Teacher()));//输出 1 
  14.         System.out.println(td2.get(new Teacher()));//输出 2 
  15.         System.out.println(td3.get(new Teacher()));//输出 3 
  16.         System.out.println(td4.get(new Teacher()));//输出 4 
  17.         System.out.println(td5.get(new Teacher()));//输出 5 

六、函数式接口

Supplier:代表一个输出

Consumer:代表一个输入

BiConsumer:代表两个输入

Function:代表一个输入,一个输出(一般输入和输出是不同类型的)

UnaryOperator:代表一个输入,一个输出(输入和输出是相同类型的)

BiFunction:代表两个输入,一个输出(一般输入和输出是不同类型的)

BinaryOperator:代表两个输入,一个输出(输入和输出是相同类型的)

在Java中提供了一系列的函数式接口,用来接受后续传入的逻辑,但是对输入和输出有要求

1 Supplier:代表一个输出

  1. Supplier s1 = ()->{return "muxiaonong";}; 
  2.     Supplier s2 = ()->"muxiaonong2"
  3.     System.out.println(s1.get());//输出 muxiaonong 
  4.     System.out.println(s2.get());//输出 muxiaonong2 

2 Consumer:代表一个输入

  1. Consumer c11 = (str) -> System.out.println(str); 
  2.    c11.accept("beijing");//输出 beijing 

3 BiConsumer:代表两个输入

  1. BiFunctionInteger> bf = (a,b)->a.length()+b.length(); 
  2.      System.out.println(bf.apply("大吉大利""今晚吃鸡"));//输出一个字符串长度 8  

4 Function:代表一个输入,一个输出

  1. //  FunctionInteger>  用来接收后面的函数的实现,规定必须有一个输入(String)有一个输出(Integer
  2.  FunctionInteger> f1 = (str)->{return str.length();}; 
  3.  System.out.println(f1.apply("abcdefg"));//输出长度 7  

七、方法的引用

方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法,方法引用提供了一种引用而不执行方法的方式,如果抽象方法的实现恰好可以使用调用另外一个方法来实现,就有可能可以使用方法引用

1 方法引用的分类

2 静态方法引用

静态方法引用: 如果函数式接口的实现恰好可以通过 调用一个静态方法 来实现,那么就可以使用静态方法引用

  1.  
  2. public class Test2 { 
  3.     //无参静态方法 
  4.      static String put(){ 
  5.             System.out.println("put....."); 
  6.             return "put"
  7.         } 
  8.  
  9.     //有参静态方法 
  10.     public static void getSize(int size){ 
  11.             System.out.println(size); 
  12.         } 
  13.  
  14.      //有参 有返回值静态方法 
  15.      public static String toUpperCase(String str){ 
  16.             return str.toUpperCase(); 
  17.         } 
  18.  
  19.     //两个入参,一个返回值静态方法 
  20.     public static Integer getLength(String str,String str2){ 
  21.         return str.length()+str2.length(); 
  22.     } 
  23.  
  24.       public static void main(String[] args) { 
  25.         //无参静态方法-普通调用 
  26.         System.out.println(put());//输出put 
  27.         //无参静态方法-原生调用 
  28.         Supplier s1 = ()-> Test2.put(); 
  29.         System.out.println(s1.get());//输出put 
  30.         //无参静态方法-静态方法引用 
  31.         Supplier s2 = Test2::put; 
  32.         System.out.println(s2.get());//输出put 
  33.         //无参静态方法-内部类调用 
  34.         Supplier s3 = Fun::hehe; 
  35.         System.out.println(s3.get()); //输出hehe 
  36.  
  37.         // 有参静态方法-静态方法引用 
  38.         Consumer<Integer> c1 = Test2::getSize; 
  39.         Consumer<Integer> c2 = (size)-> Test2.getSize(size); 
  40.         c1.accept(123); 
  41.         c2.accept(111); 
  42.  
  43.         //有参有返回值静态方法 
  44.         Function f1 = (str)->str.toUpperCase(); 
  45.         Function f2 = (str)-> Test2.toUpperCase(str); 
  46.         Function f3 = Test2::toUpperCase; 
  47.         Function f4 = Test2::toUpperCase; 
  48.  
  49.         System.out.println(f1.apply("abc"));//输出 ABC  
  50.         System.out.println(f2.apply("abc"));//输出 ABC  
  51.         System.out.println(f3.apply("abc"));//输出 ABC  
  52.         System.out.println(f4.apply("abc"));//输出 ABC  
  53.  
  54.         // 两个参数 一个返回值 函数式接口 
  55.          BiFunctionInteger> bf = (a, b)->a.length()+b.length(); 
  56.         BiFunctionInteger> bf2 = Test2::getLength; 
  57.         System.out.println(bf2.apply("abc""def"));//输出 6 
  58.         System.out.println(bf.apply("abc""def"));//输出 6 
  59.  
  60.     } 
  61.  
  62.     //内部类 
  63.     class Fun { 
  64.         public static String hehe(){ 
  65.             return "hehe"
  66.         } 
  67.  
  68.         public static String toUpperCase(String str){ 
  69.             return str.toUpperCase(); 
  70.         } 
  71.  
  72.     } 
  73.  

3 实例方法引用

实例方法引用: 如果函数式接口的实现恰好可以通过调用一个实例的实例方法来实现,那么就可以使用实例方法引用

  1. public class Test3 { 
  2.     //实例无参方法 
  3.     public String put(){ 
  4.         return "put..."
  5.     } 
  6.  
  7.     //实例有参方法 
  8.     public void getSize(int size){ 
  9.         System.out.println("size:"+size); 
  10.     } 
  11.  
  12.     //实例有参有返回值方法 
  13.     public String toUpperCase(String str){ 
  14.         return  str.toUpperCase(); 
  15.     } 
  16.     public static void main(String[] args) { 
  17.         //实例无参方法返回-普通调用 
  18.         System.out.println(new Test3().put());//输出 put... 
  19.         Supplier s1 = ()->new Test3().put(); 
  20.         Supplier s2 = ()->{return new Test3().put();}; 
  21.         Supplier s3 = new Test3()::put; 
  22.         System.out.println(s1.get());//输出 put... 
  23.         System.out.println(s2.get());//输出 put... 
  24.         System.out.println(s3.get());//输出 put... 
  25.  
  26.         //唯一的创建一个test3对象 
  27.         Test3 test = new Test3(); 
  28.  
  29.         Consumer<Integer> c1 = (size)->new Test3().getSize(size); 
  30.         Consumer<Integer> c2 = new Test3()::getSize; 
  31.         Consumer<Integer> c3 = test::getSize; 
  32.  
  33.  
  34.         c1.accept(123);//输出 size:123 
  35.         c2.accept(123);//输出 size:123 
  36.         c3.accept(123);//输出 size:123 
  37.  
  38.         Function f1 = (str)->str.toUpperCase(); 
  39.         Function f2 = (str)->test.toUpperCase(str); 
  40.         Function f3 = new Test3()::toUpperCase; 
  41.         Function f4 = test::toUpperCase; 
  42.         System.out.println(f1.apply("abc"));//输出 ABC 
  43.         System.out.println(f2.apply("abc"));//输出 ABC 
  44.         System.out.println(f3.apply("abc"));//输出 ABC 
  45.         System.out.println(f4.apply("abc"));//输出 ABC 
  46.     } 

4 对象方法引用

对象方法引用: 抽象方法的第一个参数类型刚好是实例方法的类型,抽象方法剩余的参数恰好可以当做实例方法的参数。如果函数式接口的实现能由上面说的实例方法调用来实现的话,那么就可以使用对象方法引用

  1.  
  2. public class Test4 { 
  3.     public static void main(String[] args) { 
  4.         Consumer c1 = (too)->new Too().foo(); 
  5.         c1.accept(new Too());//输出 foo 
  6.  
  7.         Consumer c2 = (Too too) ->new Too2().foo(); 
  8.         c2.accept(new Too());//输出 foo---too2 
  9.  
  10.         Consumer c3 = Too::foo; 
  11.         c3.accept(new Too());//输出 foo 
  12.  
  13.         BiConsumer bc = (too2,str)->new Too2().show(str); 
  14.         BiConsumer bc2 = Too2::show; 
  15.         bc.accept(new Too2(),"abc"); 
  16.         bc2.accept(new Too2(),"def"); 
  17.  
  18.         BiFunction<Exec,String,Integer> bf1 = (e,s)->new Exec().test(s); 
  19.         bf1.apply(new Exec(),"abc"); 
  20.         BiFunction<Exec,String,Integer> bf2 = Exec::test; 
  21.         bf2.apply(new Exec(),"def"); 
  22.     } 
  23.  
  24. class Exec
  25.     public int test(String name){ 
  26.         return 1; 
  27.     } 
  28.  
  29.  
  30. class Too{ 
  31.     public Integer fun(String s){ 
  32.         return 1; 
  33.     } 
  34.     public void foo(){ 
  35.         System.out.println("foo"); 
  36.     } 
  37. class Too2{ 
  38.     public Integer fun(String s){ 
  39.         return 1; 
  40.     } 
  41.     public void foo(){ 
  42.         System.out.println("foo---too2"); 
  43.     } 
  44.  
  45.     public void show(String str){ 
  46.         System.out.println("show ---too2"+str); 
  47.     } 

5 构造方法引用

构造方法引用: 如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用

  1.  
  2. public class Test5 { 
  3.     public static void main(String[] args) { 
  4.         Supplier s1 = ()->new Person(); 
  5.         s1.get();//输出 调用无参的构造方法 
  6.         Supplier s2 = Person::new; 
  7.         s2.get();//输出 调用无参的构造方法 
  8.  
  9.         Supplier s3 = ArrayList::new; 
  10.         Supplier<Set> s4 = HashSet::new; 
  11.         Supplier s5 = Thread::new; 
  12.         Supplier s6 = String::new; 
  13.  
  14.         Consumer<Integer> c1 = (age)->new Account(age); 
  15.         Consumer<Integer> c2 = Account::new; 
  16.         c1.accept(123);// 输出 age 参数构造123 
  17.         c2.accept(456);//输出 age 参数构造456 
  18.  
  19.         Function f1 = (str)->new Account(str); 
  20.         Function f2 = Account::new; 
  21.         f1.apply("abc");//输出 str 参数构造abc 
  22.         f2.apply("def");//输出 str 参数构造def 
  23.  
  24.     } 
  25.  
  26. class Account{ 
  27.     public Account(){ 
  28.         System.out.println("调用无参构造方法"); 
  29.     } 
  30.  
  31.     public Account(int age){ 
  32.         System.out.println("age 参数构造" +age); 
  33.     } 
  34.  
  35.     public Account(String str){ 
  36.         System.out.println("str 参数构造" +str); 
  37.     } 
  38.  
  39. class Person{ 
  40.     public Person(){ 
  41.         System.out.println("调用无参的构造方法"); 
  42.     } 

八、小结

 

来源:牧小农内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯