函数式接口
简单来说,函数式接口是只包含一个抽象方法的接口。
当然可以包含其他方法,(默认,静态,私有)方法。
java 8提供 @FunctionalInterface作为注解,检测是否是函数式接口
函数式编程
Lambda的延迟执行:
有些场景代码执行后,结果不一定会被使用,从而造成性能浪费,而Lambda是延迟执行的,这正好可以解决作为结局方案,提升性能。
例如如下代码,
public static void shouLog(int level,String message){
if(level==1){
System.out.println(message);
}
}
public static void main(String[] args) {
String msg1="hallo";
String msg2="world";
String msg3="java";
shouLog(1,msg1+msg2+msg3);
}
可以知道,当 level==1 时,会执行三个字符串的拼接,并且输出拼接字符串,而level 不等于1时,任然会执行三个字符串的拼接,但是不输出任何结果。于是这种情况里就出现了,性能浪费的时候。
利用Lambda延迟执行如下:
使用Lambda函数式的前提必须继承函数式接口;
@FunctionalInterface
public interface MessageBuilder {
//定义一个函数式接口里的拼接字符的抽象方法
public abstract String builderString();
}
public class DemoLogger {
public static void shouLog(int level,MessageBuilder message){
if(level==1){
System.out.println(message.builderString());
}
}
public static void main(String[] args) {
String msg1="hallo";
String msg2="world";
String msg3="java";
shouLog(1,()-> {return msg1+msg2+msg3;});
}
}
执行结果,完全相同;
shouLog(2, ()->{
System.out.println("不满足条件不执行");
return msg1+msg2+msg3;
});
而此时,当我们将level不等于1时,不会调用builderString的方法。并没有打印出“不满足条件不执行”。
这就很好的解决了性能浪费的问题。
函数式接口作为方法的参数
在线程当中,Runnable接口就是典型的函数式接口,里面只有一个run方法。所以在线程的调用过程中,我们就可以使用Runnable这样的接口作为函数的参数。
public class Demo01Runnable {
public static void main(String[] args) {
startThread(new Runnable() {
@Override
public void run() {
System.out.println("线程启动了"+"-->"+Thread.currentThread().getName());
}
});
}
//定义一个方法,开启线程
public static void startThread(Runnable run){
new Thread(run).start();
}
用Lambda表达式优化:
//Lambda表达式简化后
startThread(()->
System.out.println("线程启动了"+"-->"+Thread.currentThread().getName())
);
总结两种方式的区别:
根本在于,前者是创建了一个匿名内部类,进行方法重写之后的调用,实际上创建了一个匿名对象,而后者则是省略了对象的创建。提高了性能。
执行结果:
函数式接口作为返回类型时:
如Comparator 比较器;只有Compare的抽象方法;
(可以理解为定义一种比较方式,比较的时候用Arrays.sort(参数就放,自己重写的compare方法),这里返回的正式这种排序方式)
public class DemoCompare {
public static void main(String[] args) {
String[] arr={"aaa","bb","aaaaaa","cccc"};
System.out.println(Arrays.toString(arr));
Arrays.sort(arr,getCompare());
System.out.println(Arrays.toString(arr));
}
public static Comparator<String> getCompare(){
// return new Comparator<String>() {
// @Override
// public int compare(String o1, String o2) {
// return o2.length()-o1.length();
// }
// };
//优化
return (o1, o2) ->o2.length()-o1.length();
}
}
结果:
注: jdk中提供了大量的函数式接口以丰富Lamnda表达式的使用场景,它们主要在Java.util.function包中被提供。如:supplier,Comsumer接口等,lambda表达式,省略了,对接口的创建继承实现类,将方法的重写步骤放置到了,调用我们需要用到的个方法时。