Lambda表达式
什么是lambda表达式
lamda表达式是一种Java用于实现函数式接口 的一种书写形式。
首先,它是一个书写形式,是一种语法规则 ,不是什么函数之类的东西。
书写形式
既然Lambda是一种书写形式,那应该怎么书写呢?
类似于: (参数)->{逻辑体},
具体书写如下:
可以清晰的看到,后面的Comparator是使用Lambda表达式来书写的,这是因为Comparator是一个函数式接口。
函数式接口就能写成Lambda表达式的形式。
函数式接口
上面说到函数式接口,什么是函数式接口
- 首先它是一个接口
- 里面只有一个抽象方法
- 可以有默认方法和静态方法
总之!!!函数式接口只能有一个抽象方法,而且被@FunctionalInterface注解: 比如Comparator。
下面是去源码里截取的部分方法。
java
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}
public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
return Collections.reverseOrder();
}
你可以观察到里面有default(默认)和static(静态)方法 , 但是只有一个抽象方法compare()
但是你能看见它好像还有一个抽象方法equals(), 先说结论这个不算是它的抽象方法,而是它从Object那里继承来的,写在这里只是表示实现这个接口的类必须去实现这个方法。但是呢,任何类都默认有实现,从Object那里继承来的实现,所以一般是不用再重写的
所以, Comparator算是一个函数式接口。
所有的函数式接口都可以使用Lambda,包括我们自己造的函数式接口:
java
public class MyClass{
public static void main(String[] args) {
addMethod(5,6, (a,b)->{
return a+b;
});
}
public static void addMethod(int a, int b, MyFunction myFunction){
}
}
@FunctionalInterface
interface MyFunction {
int add(int a, int b);
}
java里的函数式接口Function
源码里的结构:
csharp
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
有传参(T),有返回值(R)
看看怎么使用吧:
arduino
public class MyClass{
public static void main(String[] args) {
System.out.println(method(5, o1 -> o1 - 1));
}
// 这里写上参数和返回值的类型哦
public static int method(int a, Function<Integer, Integer> myFunction){
return myFunction.apply(a);
}
}
在要使用的地方传具体的类型即可,很简单
java里的函数式接口Supplier(供给者)
源码里的结构:
csharp
@FunctionalInterface
public interface Supplier<T> {
T get();
}
无传入,但是有返回值(T)。
使用:
arduino
public class MyClass{
public static void main(String[] args) {
addMethod(5,6, ()-> 5);
}
// 这里定义返回类型
public static void addMethod(int a, int b, Supplier<Integer> myFunction){}
}
java里的函数式接口Consumer(消费者)
csharp
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
有传入,无返回,白嫖怪
使用:
typescript
public class MyClass{
public static void main(String[] args) {
method(5, (o1)-> {
System.out.println("消费" + o1);
});
}
// 定义参数类型
public static void method(int a, Consumer<Integer> myFunction){
myFunction.accept(a);
}
}
java里的函数式接口Predicate(断言)
源码里的结构:
复合条件的返回true,不符合的返回false
java
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
使用:
typescript
public class MyClass{
public static void main(String[] args) {
System.out.println(method(0, o -> o > 1));
}
public static boolean method(Integer integer ,Predicate<Integer> myFunction){
return myFunction.test(integer);
}
}
作用
对于我来说最直观的作用就是书写简便。
对于Java来说是有对性能的提升的:我们不使用lambda就只能使用匿名内部类,但是大多数情况下匿名内部类的效率是低于lambda的。
原因:对于匿名内部类,编译器会为每一个匿名内部类创建相应的类文件。一般的程序,往往回调接口会有很多。这样就会生成很多的类文件,因为类在使用之前需要加载类文件并进行验证,这个过程就会影响应用的性能。
Lambda表达式虽然推导到相应的函数式接口,但并没有编译成匿名内部类的方式来处理,而做成是直接方法调用。(为什么这样的逻辑我搞不懂,反正比匿名快)
然后Java还有其它内置接口,慢慢探索吧,我也用不到那么多。
下节预告: 【函数式编程】方法引用