简单理解Lambda表达式
1. 什么是函数式接口?
. 函数式接口在Java中是指:有且仅有一个抽象方法的接口。
函数式接口,即适用于函数式编程场景的接口。而Java中的函数式编程体现就是Lambda,所以函数式接口就 是可以适用于Lambda使用的接口。只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行 推导。
与@Override注解的作用类似,Java 8中专门为函数式接口引入了一个新的注解:@FunctionalInterface。该注解可用于一个接口的定义上:
比如多线程中的Runnable接口:
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
2.Lambda表达式的举例使用
在有Lanmbda表达式前怎么开启一条线程?
例:
//使用匿名内部类直接开启一条线程
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("The old runable now is using!");
}
}).start();
使用Lanmbda表达式开启一条线程
例:
//使用匿名内部类直接开启一条线程
new Thread(() -> System.out.println("The old runable now is using!")).start();
使用Lanmbda表达式的代码要简洁的多,所以在使用函数式接口时可以考虑使用Lanmbda表达式。
NEW一个Thread对象需要传入一个实现了Runnable接口的参数,以上例子中可以看出匿名内部类和Lanmbda表达式是等效的。
解析:
匿名内部类就是为了实现一个Runable接口并重写run方法。还可以通过一个类实现Runable接口并重写run方法,再创建此类对象作为参数开启线程。最终目的都只是为了重写一个run方法。而Lanmbda表达式可以省去创建实现Runable接口的对象而直接重写run方法。只有函数式接口才能使用Lanmbda表达式:
Lambda语法:() ->{}
“()”内代替抽象方法的参数,"{ }"内代替抽象方法的方法体
可以把Lanmbda表达式看做一个整体来理解:
() -> System.out.println("The old runable now is using!") ----------->看做为一个整体,设为X, X是一个实现了Runable接口并重写了run方法的对象
再把X做参数代入
new Thread(X).start();
Lanmbda的延迟执行:
一种典型的场景就是对参数进行有条件使用,例如对日志消息进行拼接后,在满足条件的情况下进行打印输出:
public class Demo01Logger {
private static void log(int level, String msg) {
if (level == 1) {
System.out.println(msg);
}
}
public static void main(String[] args) {
String msgA = "Hello";
String msgB = "World";
String msgC = "Java";
log(1, msgA + msgB + msgC);
}
}
这段代码存在问题:无论级别是否满足要求,作为log方法的第二个参数,三个字符串一定会首先被拼接并传入方法内,然后才会进行级别判断。如果级别不符合要求,那么字符串的拼接操作就白做了,存在性能浪费。
利用Lambda的延迟执行优化
使用Lambda必然需要一个函数式接口:
//自定义接口
@FunctionalInterface
public interface MessageBuilder {
String buildMessage();
}
然后对log方法进行改造:
public class Demo02LoggerLambda {
private static void log(int level, MessageBuilder builder) {
if (level == 1) {
System.out.println(builder.buildMessage());
}
}
public static void main(String[] args) {
String msgA = "Hello";
String msgB = "World";
String msgC = "Java";
log(1, () -> msgA + msgB + msgC );
}
}
这样一来,只有当级别满足要求的时候,才会进行三个字符串的拼接;否则三个字符串将不会进行拼接。
图解:
证明Lambda的延迟
public class Demo03LoggerDelay {
private static void log(int level, MessageBuilder builder) {
if (level == 1) {
System.out.println(builder.buildMessage());
}
}
public static void main(String[] args) {
String msgA = "Hello";
String msgB = "World";
String msgC = "Java";
log(2, () -> {
System.out.println("Lambda执行!");
return msgA + msgB + msgC;
});
}
}
在不符合级别要求的情况下,Lambda将不会执行。从而达到节省性能的效果。
注:我是说看成为一个对象,是可以这样理解来使用,而不是说Lambda就是一个对象.
以上内容只是帮助快速理解Lambda表达式的作用与写法