Lambda表达式是java8新具有的特性;
主要结构: (param1,param2)-> {语句 ;} / 表达式; 例如:(String str1,String str2)->{System.out.println(str1+str2);}
当参数只有一个且类型可以推断出来的时候参数列表的()可以不用写 例如:a ->a;
-> 后面可以跟表达式,也可以跟语句; 当根表达式的时候,不用写return ;直接表达式的结果就是返回的结果;
例如: int i ->i;
->后面也可以跟语句;如果是语句的话需要用{}包含;且{}中的语句需要用;结尾,且要是有返回值的话必须写return 语句;
例如: int a ->{return a;}
Lambda表达式在其他语言里面是一个方法;但是在Java中是一个对象; 它传递是一种行为,而不仅仅是值;
应用场景:函数式接口(只有在需要函数式接口的时候才需可以传递 Lambda);
函数式接口:1.有且只有一个抽象方法的接口;
2.在接口上可以写注解@FunctionalInterface 来规范函数式接口;加注解后当语法不满足函数式接口的话会 提醒报错;
3.当格式语法符合函数式接口时,不需要注解也会被当做函数式接口;
4.当接口中声明Object类中的方法时,默认接口中的抽象方法数量不会增加(也就是说该方法会被忽略); 因为接口的实现类会默认的继承Object类,相当于是重写了Object类的方法,而不是实现接口的方法,所 以 也就不会被识别到;
5.任何函数式接口都不允许抛出受检异常;如果需要Lambda表达式抛出异常的话有两种方式:
(1)在抽象方法定义的时候就显式的抛出异常;
(2)在Lambda表达式上使用try {} catch(){}块来捕捉异常;
例如:
class Test{
public static void main(String args[]){
Compare com=(int x,int y)->x+y;
System.out.println("结果是:"+com.compareInteger(3,4));
}
}
interface Compare{
Integer compareInteger(int i,int j);
}
函数描述符:
函数式接口的抽象方法的签名基本上就是Lambda表达式的签名;这种抽象方法的签名叫做函数描述符;
例如:Runnable接口中的run()方法;既不接受参数,也不返回值;其签名为 ()->void;
javaAPI中:常用的泛型函数式接口:
(1)Predicate ; T ->boolean 其接收一个对象,返回一个布尔值
(2)Consumer ; T -> void 接收一个对象,什么都不返回(consumer消费者;相当于消费了一个对象)
(3) Function ; T -> R 接受一个对象,返回一个对象
(4)supplier ; void -> T (supplier提供者)
(5)UnaryOperator T -> T
(6) BinAryOperator :(T,T) -> T
(7) BiPredicate ; (L,R) ->boolean ;
(8) BiConsumer ; (T, U) ->void ;
(9)BiFunction ; (T ,U ) ->R;
高阶函数:当一个函数接受一个函数类型的参数或者返回一个函数的时候,该方法被称为高阶函数;
Function函数式接口:
方法: (1) R apply(T t); : T -> R
(2) default <V> Function<V, R> compose(Function<? super V, ? extends T> before)
{Objects.requireNonNull(before); return (V v) -> apply(before.apply(v));}
该方法接受一个Function类型的对象,当该方法执行的时候,先执行参数的方法;再将前面执行的结果作为一个参 数执行当前的方法;相当于在当前方法执行之前执行参数的方法;两个方法之间是串行关系;
(3) default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); }
该方法和上面的方法一样,接收一个Function类型的对象,但是当该方法执行时:先执行当前的方法,再将当前方 法的执行结果作为参数执行参数对象的方法;相当于在当前方法执行之后执行参数方法;两个方法之间也是串行;
import java.util.function.Function;
class Test{
public static void main(String args[]){
Test test=new Test();
System.out.println(test.out("hello", value->value+"1", value->value+"2"));
}
String out(String str1,Function<String, String> function,Function<String, String> function2){
return function.compose(function2).apply(str1);
}
}
输出结果: hello21
BiFunction函数式接口:
(1) R apply(T t, U u); (T,U) ->R
(2) default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after); return (T t, U u) -> after.apply(apply(t, u));
}
同样他也有和Function接口一样的andThen()函数; 但是他 的参数确是Funcion类型;原因是BiFunction是接收两 个参数;最后返回一个值;如果他接受的参数类型是BiFunction ;则参数列表的个数不符合要求;
这同样也是BiFunction没有compose()方法的原因;
其他的函数式接口可以去看java源代码,应该比较好理解;
Lambda表达式传递的是行为?
我们之前的对于逻辑的处理基本就是面向对象的,每个方法实现一个功能;之后调用该对象的相应方法来实现相应的功能;
例如:
class Test{
public static void main(String args[]){
Test test=new Test();
test.add(1, 3);
test.mul(1, 3);
}
public int add(int a,int b){
return a+b;
}
public int mul(int a,int b){
return a*b;
}
}
而Lambda表达式相当于面向函数的;他将函数的功能抽出来,在用到该函数的时候自定义其实现的功能;
比如上面的代码可以改为 :
class Test{
public static void main(String args[]){
Test test=new Test();
System.out.println( test.getMath(1, 3, (a,b)->a+b));
System.out.println( test.getMath(1, 3, (a,b)->a*b));
}
public Integer getMath(int a,int b,BiFunction<Integer, Integer,Integer> function){
return function.apply(a,b);
}
}
getMath()方法传递BiFunction函数式接口作为参数;(T,R)->U ; 从而实现传入两个值,返回一个结果的功能;具体对参数的操作自己定义;也就相当于调用该方法时传递一个动作给方法本身,方法本身执行这个动作就可以了;