一、Lambda表达式的介绍
- Lambda表达式是 Java8 中最重要的新功能之一。使用 Lambda 表达式可以替代只有一个抽象函数的接口实现,告别匿名内部类,代码看起来更简洁易懂。Lambda表达式同时还提升了对集合、框架的迭代、遍历、过滤数据的操作。
- lambda表达式可以替代只有一个抽象函数的接口实现,告别匿名内部类,代码看起来更简洁易懂
- lambda表达式同时还提升了对集合、框架的迭代、遍历、过滤数据的操作
- lambda可以极大的减少代码冗余,同时代码的可读性要好过冗长的内部类,匿名类
例如以前我们使用匿名内部类来实现代码:
- Runnablerunnable=newRunnable(){
- @Override
- publicvoidrun(){
- System.out.println("running1…..");
- }
- };
- runnable.run();
使用lambda表达式实现更简洁的代码:
- Runnablerunnable3=()->System.out.println("running2….");
- runnable3.run();
lambda表达式语法:
在这里插入图片描述
args -> expr或者(object … args)-> {函数式接口抽象方法实现逻辑}
1、()参数的个数,根据函数式接口里面抽象的参数个数来决定,当参数只有一个的时候,()可以省略
2、当expr逻辑非常简单的时候,{}和return可以省略
案例说明:
- publicstaticvoidmain(String[]args)throwsException{
- Callable<String>c1=newCallable(){
- @Override
- publicStringcall()throwsException{
- return"muxiaonong";
- }
- };
- System.out.println(c1.call());
- Callable<String>c2=()->{return"muxiaonong2";};
- System.out.println(c2.call());
- //逻辑很简单的时候省略{}和return
- Callable<String>c3=()->"muxiaonong3";
- System.out.println(c3.call());
- }
二、Lambda表达式的特点
- 函数式编程
- 参数类型自动推断
- 代码量少,简洁
三、Lambda表达式案例
实现方式列表:
- ()->{}
- ()->{System.out.println(1);}
- ()->System.out.println(1)
- ()->{return100;}
- ()->100
- ()->null
- (intx)->{returnx+1;}
- (intx)->x+1
- (x)->x+1
- x->x+1
案例1:线程实现方式:
- publicstaticvoidmain(String[]args){
- //匿名内部类方式
- newThread(newRunnable(){
- @Override
- publicvoidrun(){
- System.out.println("runing1……….");
- }
- });
- //Lambda表达式方式
- newThread(()->{System.out.println("runing2…..");}).start();
- }
案例2:集合遍历实现方式
- publicstaticvoidmain(String[]args){
- List<String>list=Arrays.asList("java","python","scala","javascript");
- //普通匿名内部类方式
- Collections.sort(list,newComparator<String>(){
- @Override
- publicintcompare(Stringo1,Stringo2){
- returno1.length()-o2.length();
- }
- });
- //Lambda方式
- Collections.sort(list,(a,b)->a.length()-b.length());
- list.forEach(System.out::println);
- }
四、Lambda表达式的应用场景
重要的事情说三遍:任何有函数式接口的地方 * 3
什么是函数式接口: 只有一个抽象方法(Object类中的方法除外)的接口是函数式接口
五、Lambda表达式实际应用
5.1 无参实体类模拟
模拟数据库连接层:
- @FunctionalInterface
- publicinterfaceStudentDao{
- voidinsert(Studentstudent);
- }
实体类
- /**@Authormxn
- *@Description学生实体类
- *@Date10:192020/11/7
- *@Param
- *@return
- **/
- publicclassStudent{
- }
- publicstaticvoidmain(String[]args){
- StudentDaosd1=newStudentDao(){
- @Override
- publicvoidinsert(Studentstudent){
- System.out.println("插入学生1");
- }
- };
- StudentDaosd2=(student)->{
- System.out.println("student:"+student);
- };
- StudentDaosd3=(Studentstudent)->System.out.println("student3:"+student);
- sd1.insert(newStudent());//输出插入学生1
- sd2.insert(newStudent());//输出
- sd3.insert(newStudent());//输出
- }
5.2 有参实体类模拟
实体类
- /**@Authormxn
- *@Description
- *@Date10:262020/11/7
- *@Param
- *@return
- **/
- publicclassTeacher{
- }
接口模拟层
- @FunctionalInterface
- publicinterfaceTeacherDao{
- intget(Teacherteacher);
- }
实现层
- publicstaticvoidmain(String[]args){
- TeacherDaotd1=newTeacherDao(){
- @Override
- publicintget(Teacherteacher){
- return1;
- }
- };
- TeacherDaotd2=(teacher)->{return2;};
- TeacherDaotd3=(Teacherteacher)->{return3;};
- TeacherDaotd4=(teacher)->4;
- TeacherDaotd5=(Teacherteacher)->5;
- System.out.println(td1.get(newTeacher()));//输出1
- System.out.println(td2.get(newTeacher()));//输出2
- System.out.println(td3.get(newTeacher()));//输出3
- System.out.println(td4.get(newTeacher()));//输出4
- System.out.println(td5.get(newTeacher()));//输出5
- }
六、函数式接口
Supplier:代表一个输出
Consumer:代表一个输入
BiConsumer:代表两个输入
Function:代表一个输入,一个输出(一般输入和输出是不同类型的)
UnaryOperator:代表一个输入,一个输出(输入和输出是相同类型的)
BiFunction:代表两个输入,一个输出(一般输入和输出是不同类型的)
BinaryOperator:代表两个输入,一个输出(输入和输出是相同类型的)
在Java中提供了一系列的函数式接口,用来接受后续传入的逻辑,但是对输入和输出有要求
6.1 Supplier:代表一个输出
- Supplier<String>s1=()->{return"muxiaonong";};
- Supplier<String>s2=()->"muxiaonong2";
- System.out.println(s1.get());//输出muxiaonong
- System.out.println(s2.get());//输出muxiaonong2
6.2 Consumer:代表一个输入
- Consumer<String>c11=(str)->System.out.println(str);
- c11.accept("beijing");//输出beijing
6.3 BiConsumer:代表两个输入
- BiFunction<String,String,Integer>bf=(a,b)->a.length()+b.length();
- System.out.println(bf.apply("大吉大利","今晚吃鸡"));//输出一个字符串长度8
6.4 Function:代表一个输入,一个输出
- //Function<String,Integer>用来接收后面的函数的实现,规定必须有一个输入(String)有一个输出(Integer)
- Function<String,Integer>f1=(str)->{returnstr.length();};
- System.out.println(f1.apply("abcdefg"));//输出长度7
七、方法的引用
方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法,方法引用提供了一种引用而不执行方法的方式,如果抽象方法的实现恰好可以使用调用另外一个方法来实现,就有可能可以使用方法引用
7.1 方法引用的分类
7.2 静态方法引用
静态方法引用: 如果函数式接口的实现恰好可以通过 调用一个静态方法 来实现,那么就可以使用静态方法引用
- /**
- *@program:lambda
- *@ClassNameTest2
- *@description:
- *@author:muxiaonong
- *@create:2020-10-2822:15
- *@Version1.0
- **/
- publicclassTest2{
- //无参静态方法
- staticStringput(){
- System.out.println("put…..");
- return"put";
- }
- //有参静态方法
- publicstaticvoidgetSize(intsize){
- System.out.println(size);
- }
- //有参有返回值静态方法
- publicstaticStringtoUpperCase(Stringstr){
- returnstr.toUpperCase();
- }
- //两个入参,一个返回值静态方法
- publicstaticIntegergetLength(Stringstr,Stringstr2){
- returnstr.length()+str2.length();
- }
- publicstaticvoidmain(String[]args){
- //无参静态方法-普通调用
- System.out.println(put());//输出put
- //无参静态方法-原生调用
- Supplier<String>s1=()->Test2.put();
- System.out.println(s1.get());//输出put
- //无参静态方法-静态方法引用
- Supplier<String>s2=Test2::put;
- System.out.println(s2.get());//输出put
- //无参静态方法-内部类调用
- Supplier<String>s3=Fun::hehe;
- System.out.println(s3.get());//输出hehe
- //有参静态方法-静态方法引用
- Consumer<Integer>c1=Test2::getSize;
- Consumer<Integer>c2=(size)->Test2.getSize(size);
- c1.accept(123);
- c2.accept(111);
- //有参有返回值静态方法
- Function<String,String>f1=(str)->str.toUpperCase();
- Function<String,String>f2=(str)->Test2.toUpperCase(str);
- Function<String,String>f3=Test2::toUpperCase;
- Function<String,String>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<String,String,Integer>bf=(a,b)->a.length()+b.length();
- BiFunction<String,String,Integer>bf2=Test2::getLength;
- System.out.println(bf2.apply("abc","def"));//输出6
- System.out.println(bf.apply("abc","def"));//输出6
- }
- //内部类
- classFun{
- publicstaticStringhehe(){
- return"hehe";
- }
- publicstaticStringtoUpperCase(Stringstr){
- returnstr.toUpperCase();
- }
- }
- }
7.3 实例方法引用
实例方法引用: 如果函数式接口的实现恰好可以通过调用一个实例的实例方法来实现,那么就可以使用实例方法引用
- publicclassTest3{
- //实例无参方法
- publicStringput(){
- return"put…";
- }
- //实例有参方法
- publicvoidgetSize(intsize){
- System.out.println("size:"+size);
- }
- //实例有参有返回值方法
- publicStringtoUpperCase(Stringstr){
- returnstr.toUpperCase();
- }
- publicstaticvoidmain(String[]args){
- //实例无参方法返回-普通调用
- System.out.println(newTest3().put());//输出put…
- Supplier<String>s1=()->newTest3().put();
- Supplier<String>s2=()->{returnnewTest3().put();};
- Supplier<String>s3=newTest3()::put;
- System.out.println(s1.get());//输出put…
- System.out.println(s2.get());//输出put…
- System.out.println(s3.get());//输出put…
- //唯一的创建一个test3对象
- Test3test=newTest3();
- Consumer<Integer>c1=(size)->newTest3().getSize(size);
- Consumer<Integer>c2=newTest3()::getSize;
- Consumer<Integer>c3=test::getSize;
- c1.accept(123);//输出size:123
- c2.accept(123);//输出size:123
- c3.accept(123);//输出size:123
- Function<String,String>f1=(str)->str.toUpperCase();
- Function<String,String>f2=(str)->test.toUpperCase(str);
- Function<String,String>f3=newTest3()::toUpperCase;
- Function<String,String>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 对象方法引用
对象方法引用: 抽象方法的第一个参数类型刚好是实例方法的类型,抽象方法剩余的参数恰好可以当做实例方法的参数。如果函数式接口的实现能由上面说的实例方法调用来实现的话,那么就可以使用对象方法引用
- /**@Authormxn
- *@Description//TODO对象方法引用
- *@Date14:262020/11/7
- *@Param
- *@return
- **/
- publicclassTest4{
- publicstaticvoidmain(String[]args){
- Consumer<Too>c1=(too)->newToo().foo();
- c1.accept(newToo());//输出foo
- Consumer<Too>c2=(Tootoo)->newToo2().foo();
- c2.accept(newToo());//输出foo—too2
- Consumer<Too>c3=Too::foo;
- c3.accept(newToo());//输出foo
- BiConsumer<Too2,String>bc=(too2,str)->newToo2().show(str);
- BiConsumer<Too2,String>bc2=Too2::show;
- bc.accept(newToo2(),"abc");
- bc2.accept(newToo2(),"def");
- BiFunction<Exec,String,Integer>bf1=(e,s)->newExec().test(s);
- bf1.apply(newExec(),"abc");
- BiFunction<Exec,String,Integer>bf2=Exec::test;
- bf2.apply(newExec(),"def");
- }
- }
- classExec{
- publicinttest(Stringname){
- return1;
- }
- }
- classToo{
- publicIntegerfun(Strings){
- return1;
- }
- publicvoidfoo(){
- System.out.println("foo");
- }
- }
- classToo2{
- publicIntegerfun(Strings){
- return1;
- }
- publicvoidfoo(){
- System.out.println("foo—too2");
- }
- publicvoidshow(Stringstr){
- System.out.println("show—too2"+str);
- }
- }
7.5 构造方法引用
构造方法引用: 如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用
- /**@Authormxn
- *@Description//TODO构造方法引用
- *@Date14:272020/11/7
- *@Param
- *@return
- **/
- publicclassTest5{
- publicstaticvoidmain(String[]args){
- Supplier<Person>s1=()->newPerson();
- s1.get();//输出调用无参的构造方法
- Supplier<Person>s2=Person::new;
- s2.get();//输出调用无参的构造方法
- Supplier<List>s3=ArrayList::new;
- Supplier<Set>s4=HashSet::new;
- Supplier<Thread>s5=Thread::new;
- Supplier<String>s6=String::new;
- Consumer<Integer>c1=(age)->newAccount(age);
- Consumer<Integer>c2=Account::new;
- c1.accept(123);//输出age参数构造123
- c2.accept(456);//输出age参数构造456
- Function<String,Account>f1=(str)->newAccount(str);
- Function<String,Account>f2=Account::new;
- f1.apply("abc");//输出str参数构造abc
- f2.apply("def");//输出str参数构造def
- }
- }
- classAccount{
- publicAccount(){
- System.out.println("调用无参构造方法");
- }
- publicAccount(intage){
- System.out.println("age参数构造"+age);
- }
- publicAccount(Stringstr){
- System.out.println("str参数构造"+str);
- }
- }
- classPerson{
- publicPerson(){
- System.out.println("调用无参的构造方法");
- }
- }
八、小结
- Java8 引入 Lambda表达式是接收了函数式编程语言的思想,和指令式编程相比,函数式编程强调函数的计算比指令的执行重要。引入 Lambda表达式是接收了函数式编程语言的思想,和指令式编程相比,函数式编程强调函数的计算比指令的执行重要。引入 Lambda表达式是接收了函数式编程语言的思想,和指令式编程相比,函数式编程强调函数的计算比指令的执行重要。
- lambda表达式可以使代码看起来简洁,但一定程度上增加了代码的可读性以及调试的复杂性,所以在使用时应尽量是团队都熟悉使用,要么干脆就别用,不然维护起来是件较痛苦的事,今天的小知识就到这里了,有问题的小伙伴可以在下方进行留言,大家加油!
原文地址:https://mp.weixin.qq.com/s/9tWEoCqlEoHkKzAgMFAzzA