lambda表达式本质上是一个代码块,在Java8以前,不能直接传递一个代码块,必须构造一个对象来编写方法包含这段代码。而在此情况下,lambda横空出世。
基本形式:
参数,箭头(->),表达式
方法引用:
1、对象实例::对象方法
2、Class对象::静态方法
3、Class对象::实例方法
构造器引用
对象::new
注意点:
在lambda表达式中引用的外部变量引用必须是最终变量,即初始化以后就不可以改变,不然是不可以捕获的
lambda表达式的体和嵌套块有同样的作用域,注意命名冲突等等问题比如:
Integer a=3;
IntStream.range(0,5).map(f->{
System.out.println(this.toString());
return f*3;});
这里的a就冲突了,而this指代的也是本对象,和普通的this使用没有差别
使用lambda的重点是延迟执行,像方法一样被调用,或者是单独线程的中运行的代码等等
如果你写的方法要接受lambda表达式,需要一个函数式接口 ,以下表格均引至Java核心技术卷 卷一
函数式接口 | 参数类型 | 返回类型 | 抽象方法名 | 描述 | 其他方法 |
Runnable | 无 | void | run | 作为无参数或返回值的动作执行 | |
Supplier<T> | 无 | T | get | 提供一个T类型的值 | |
Consumer<T> | T | void | accept | 处理一个T类型的值 | andThen |
BiConsumer<T,U> | T,U | void | accept | 处理T和U类型的参数 | andThen |
Function<T,R> | T | R | apply | 有一个T类型的参数 | compose andThen identity |
BiFunction<T,U,R> | T,U | R | apply | 有T和U类型的参数 | andThen |
UnaryOperator<T> | T | T | apply | 类型T上的一元操作符 | compose andThen identity |
BinaryOperator<T> | T,T | T | apply | 类型T上的二元操作符 | andThen maxBy minBy |
Predicate<T> | T | boolean | test | 布尔值函数 | and,or negate isEqual |
BiPredicate<T,U> | T,U | boolean | test | 有两个参数的布尔值函数 | and,or negate |
函数式接口 | 参数类型 | 返回类型 | 抽象方法名 |
BooleanSupplier | none | boolean | getAsBoolean |
PSupplier | none | p | getAsP |
PConsumer | p | void | accept |
ObjPConsumer<T> | T,p | void | accept |
PFunction<T> | p | T | apply |
PToQFunction | p | q | applyAsQ |
ToPFunction<T> | T | p | applyAsP |
ToPBiFunction<T,U> | T,U | p | applyAsP |
PUnaryOperator | p | p | applyAsP |
PBinaryOperator | p,p | p | applyAsP |
PPredicate | p | boolean | test |
P、Q为Integer,Long,Double p、q为int,long,double
@FunctionalInterface注解标记的接口可以提醒编译器检查该接口是否仅仅包含一个抽象方法
下面看两个小例子:
public static void print(List<Integer> n, Consumer<Integer> consumer){
for(Integer g:n){
consumer.accept(g);
}
}
public static Double change(int g,IntToDoubleFunction toDoubleFunction){
return toDoubleFunction.applyAsDouble(g);
}
public static void main(String[] args) throws Exception{
int g=2;
System.out.println(change(g,i->Math.pow(i,i)));
print(IntStream.range(0,10).mapToObj(Integer::new).collect(Collectors.toList()),e-> System.out.println(e));
}