java8之lambda表达式用法总结
java8之lambda表达式
目的:行为参数化
Lambda表达式是简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。
Lambda的基本语法是(parameters)->expression或(parameters)->{statements;}。其中,(parameters)->expression的表达式中隐含了return,如()->42;(parameters)->{statements;}的花括号内是语句。
举例:
()->42//参数为空,返回一个int (Listlist)->list.isEmpty()//参数为list,返回一个boolean (intx,inty)->x*y//参数为两个int,返回一个int (Strings)->System.out.println(s);//参数为一个String,不返回结果 (Strings)->{System.out.println(s);}//参数为一个String,打印字符串
哪些地方使用哪些lambda
函数式接口是只定义一个抽象方法的接口,即使拥有多个默认方法。FunctionalInterface标注一个函数式接口,会加入编译检查。函数式接口中默认方法的目的是:改变已发布的接口而不破坏已有的实现。
在接受函数式接口为参数的地方,都可以使用lambda表达式。
例子:
publicvoidexecute(Runnabler){ r.run(); } execute(()->{});//使用lambda,Runnable是参数为空,没有返回值的函数式接口,即()->void //fetch返回一个函数式接口,()->String publicCallablefetch(){ return()->"Trickyexample;-)"; }
为什么只有在函数式接口的地方使用呢?lambda表达式没有函数名,只有参数列表,函数主体和返回值,如果接口有多个方法,就不能直接匹配到正确的方法上了,所以,只有一个抽象方法的函数式接口可以满足。
Predicate
java.util.function.Predicate
FunctionalInterface publicinterfacePredicate{ //接口方法,入参为泛型T,返回bool。即:(Tt)->bool booleantest(Tt); //默认方法,and操作 defaultPredicate and(Predicateother){ Objects.requireNonNull(other); return(t)->test(t)&&other.test(t); } //默认方法,取反操作 defaultPredicate negate(){ return(t)->!test(t); } //默认方法,or操作 defaultPredicate or(Predicateother){ Objects.requireNonNull(other); return(t)->test(t)||other.test(t); } //默认方法,判断是否相等 static Predicate isEqual(ObjecttargetRef){ return(null==targetRef) ?Objects::isNull :object->targetRef.equals(object); }
使用
PredicatenonEmptyStringPredicate=(Strings)->!s.isEmpty();
Consumer
java.util.function.Consumer
@FunctionalInterface publicinterfaceConsumer{ //接口方法,入参为泛型T,返回void。即:(Tt)->void voidaccept(Tt); //默认方法,可以执行级联操作 defaultConsumer andThen(Consumerafter){ Objects.requireNonNull(after); return(Tt)->{accept(t);after.accept(t);}; }
Function
java.util.function.Function
@FunctionalInterface publicinterfaceFunction{ //接口方法,入参为泛型T,返回泛型R。即:(Tt)->R Rapply(Tt); //默认方法,实现级联操作。before方法输入V,输出T,本function输入T,输出R。 default Function compose(Functionbefore){ Objects.requireNonNull(before); return(Vv)->apply(before.apply(v)); } //默认方法,级联操作 default Function andThen(Functionafter){ Objects.requireNonNull(after); return(Tt)->after.apply(apply(t)); } //默认方法,输入啥,输出啥 static Function identity(){ returnt->t; }
特定方法避免装箱操作
在处理数据时,使用特定方法,可以避免装箱操作,如:IntPredicate、LongConsumer、DoubleFunction等。具体见API库。
总结
只要函数描述符兼容,函数式接口就可以复用。
特殊的void兼容规则:
//Predicate返回了一个boolean Predicatep=s->list.add(s); //Consumer返回了一个void Consumer b=s->list.add(s);
方法引用
方法引用是调用单一方法的Lambda的快捷写法,格式ClassName::methodName。看下栗子你就懂了~
一般方法引用
(Applea)->a.getWeight()等价于Apple::getWeight ()->Thread.currentThread().dumpStack()等价于Thread.currentThread()::dumpStack (str,i)->str.substring(i)等价于String::substring (Strings)->System.out.println(s)等价于System.out::println (list,element)->list.contains(element)等价于List::contains
主要有三类:
- 指向静态方法的方法引用,如:Integer::parseInt
- 指向任意类型实例方法的方法引用,如:String::length
- 指向现有对象的实例方法的方法引用,如:User::getUserId
构造函数引用
无参构造函数
无参构造函数的函数描述符:()->T,由上面的总结知,可以使用Supplier接口,如下:
Supplierc1=User::new;//c1=()->newUser(); Useruser=c1.get();
有一个参数的构造函数
有一个参数的构造函数的函数描述符是(T)->R,可以使用Function接口,如下:
Functionc2=User::new; Useruser=c2.apply(110L);
有三个参数的构造函数
有三个参数的构造函数的函数描述符是(T,U,V)->R,没有现成的接口,需要自定义,如下:
@Data @AllArgsConstructor publicclassUser{ privateStringname; privateLonguserId; privateIntegerage; } @FunctionalInterface publicinterfaceTriFunction{ Rcreate(Tt,Uu,Vv); } publicstaticvoidmain(String[]args){ TriFunction triFunction=User::new; Useruser=triFunction.create("tina",12L,13); }
使用注意事项
Lambda表达式可以引用静态变量、成员变量和最终的(final)或事实上最终的局部变量。
更多关于java8中lambda表达式相关方法请查看下面的相关链接
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。