“我正在参与「启航方案」”
Lambd表达式
Lambda表达式是一个匿名函数,我们能够把 Lambda 表达式理解为是一段能够传递的代码(将代码 像数据相同进行传递)。能够写出更简练、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提高。
1. 格局
‘->’ :lambda操作符或箭头操作符
‘->’的左面: Lambda形参列表(其实便是接口中的抽象办法的形参列表)
‘->’的右边: Lambda体 (其实便是 重写的抽象办法的办法体)
2. Lambda表达式的运用
Lambda表达式的运用为了便利理解,分为6种情况介绍,经过内置函数式接口来举例,也能够对比匿名函数来理解。
- 语法格局一:无参,无回来值,Lambda体只需一条语句
Runnable r2 = ()->{
System.out.println("Test1");
};
- 语法格局二:Lambda需要一个参数,并且无回来值
Consumer<String> con2 = (String s)->{
System.out.println(s);
};
con2.accept("test2");
- 语法格局三:Lambda只需要一个参数时,参数的小括号能够省掉,一起省掉参数变量类型(类型揣度)
Consumer<String> con2 = s->{
System.out.println(s);
};
con2.accept("test2");
- 语法格局四:Lambda需要两个参数,并且有回来值
Comparator<Integer> com2 = (Integer o1,Integer o2) -> {
return o1.compareTo(o2);
};
- 语法格局五:当 Lambda 体只需一条语句时,return 与大括号能够省掉
Comparator<Integer> com2 = (Integer o1,Integer o2) -> o1.compareTo(o2);
- 语法格局五:数据类型能够省 略,由于可由编译器揣度得出, 称为“类型揣度
// 数据类型能够省掉,由于可由编 译器揣度得出, 称为“类型揣度
Comparator<Integer> com2 = (o1,o2) -> o1.compareTo(o2);
上述 Lambda 表达式中的参数类型都是由编译器揣度得出的。Lambda 表达式中无需指定类型,程序仍然能够编译,这是由于 javac 根据程序的上下文,在后台揣度出了参数的类型。Lambda 表达式的类型依赖于上下文环境,是由编译器揣度出来的。这便是所谓的“类型揣度”
3. 函数式接口
3.1 什么是函数式接口
只包括一个抽象办法的接口,称为函数式接口。
你能够经过 Lambda 表达式来创建该接口的目标。(若 Lambda 表达式抛出一个受检反常,那么该反常需要在目标接口的抽象办法上进行声明)。Lambda表达式也是依赖于函数式接口的。
我们能够在恣意函数式接口上运用 @FunctionalInterface 注解, 这样做能够检查它是否是一个函数式接口,一起javadoc也会包括一条声明,阐明这个接口是一个函数式接口。
3.2 如何理解函数式接口
1.Java从诞生口起便是一向倡导“全部皆目标”,在Java里面面向目标(OOP)编程是全部。但是随着python、 scala等语言的兴起和新技能的挑战,Java不得不做出调整以便支持更加广泛的技能要求,也即Java不但能够支持OOP还能够支持OOF(面向函数编程)
2.在函数式编程语言当中,函数被当做一等公民对待。在将函数作为一等公民的编程语言中,Lambda表达式的类型是函数。但是在Java8中,有所不同。在Java8中,Lambda表达式是目标,而不是函数,它们必须依附于一类特别的目标类型-函数式接口。
3.简略的说,在Java8中,Lambda表达式便是一个函数式接口的实例。这便是Lambda表达式和函数式接口的联系。也便是说,只需一少目标是函数式接口的实例,那么该目标就能够用Lambda表达式来表示。
所以曾经用匿名实现类表示的现在都能够用Lambda表达式来写。
3.3 自定义函数式接口
/**
这个接口里只能写一个办法,写多个办法注解会爆红,注解的作用是验证该接口是否是函数接口
若果不写该注解,并且接口只需一个办规律该接口也是函数式接口
*/
@FunctionalInterface
public interface MyInterface {
void method();
}
//泛型写法
@FunctionalInterface
public interface MyInterface<T> {
T method(T t);
}
3.4 Java 内置四大中心函数式接口
函数式接口 | 参数类型 | 回来类型 | 用途 |
---|---|---|---|
Consumer 消费型接口 | T | void | 对类型为T的目标使用操 作,包括办法:void accept(T t) |
Supplier供应型接口 | 无 | T | 回来类型为T的目标,包括办法:T get(); |
Function<T,R>函数型接口 | T | R | 对类型为T的目标使用操 作,并回来成果。成果 是R类型的目标。包括方 法:R apply(T t); |
Predicate断定型接口 | T | boolean | 确定类型为T的目标是否 满意某束缚,并回来 boolean 值。包括办法 boolean test(T t); |
举两个简略的比如
public void test4(){
Consume(500, new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println("消费了"+integer);
}
});
//lambda表达式写法
Consume(400,money-> System.out.println("赚了"+money));
}
public static void Consume(int money, Consumer<Integer> consumer){
consumer.accept(money);
}
public void test5(){
List<String> list = Arrays.asList("sss","rrr","yyyyy","ssdasds","sd");
list = predit(list, new Predicate<String>() {
@Override
public boolean test(String s) {
return s.length()>3;
}
});
System.out.println(list.toString());
//lambda表达式写法
List<String> list1 = Arrays.asList("12","13","14","15","16","17");
list1 = predit(list1,i->Integer.parseInt(i)>14);
System.out.println(list1.toString());
}
public static List<String> predit(List<String> strings, Predicate<String> predicate){
List<String> list = new ArrayList<>();
for (String s:strings){
if (predicate.test(s)){
list.add(s);
}
}
return list;
}
下篇预告:Stream常用的API,欢迎持续交流学习