Lambda表达式和StreamAPI
视频来源:https://www.bilibili.com/video/BV1DZRTYUEC4
Lambda表达式
Java7时,JVM引入了一个全新的指令invokedynamic (dynamic是动态的意思) 运行时函数类型动态分派;
这个指令第一次在Java语言中登场便是Lambda表达式。
java
new Thread(new Runnable(){
@Override
public void run(){
Foo.bar();
}
}).start();
在过去只能通过匿名类的方式来这么写,在Java8以前函数式编程基本不可能。
也就是说Java是没法直接传入函数作为参数的,C#通过委托机制,Java则是通过函数式接口。
拿我们熟悉的Runnable举例:
java
@FunctionalInterface
public interface Runnable{
public abstract void run();
}
简单来说,任意一个仅有一个抽象方法的接口都可以被当作函数式接口。
函数式接口的特点便是:无需像上面一样传入一个匿名类(没有变量名直接new的),而是通过()->组成的Lambda表达式
java
invokeRunnable(()->{
System.out.println(1);
});
也就是说Lambda表达式类似于满足函数式接口的特殊语法构造,在运行时会被动态转换成Runnable的接口实例(最初的那样)。
Stream API
这里的流,并不是指IO流,而是一种数据流动管道。
比如我们有一个10000容量的数组,要对每一个大于5000的数随机加一个0~500随机数,最后求和。
在过去我们可能会这样写:
java
public int sumRandomNumber(int[] array, Random random){
int rst = 0;
for(int i: array){
if(i>5000){
rst+=i+random.nextInt(500);
}
}
return rst;
}
而借助Stream API
java
public int sumRandomNumber(int[] array, Random random){
return Arrays.stream(array)//将array转换为intStream流对象
.filter(i -> i>5000)//中间函数
.map(i -> i+random.nextInt(500))//中间函数
.sum();//结尾函数
}
这里也用到了我们函数式编程涉及到的lambda表达式
拓展:算法的自定义排序
java
Arrays.sort(intervals, new Comparator<int[]>(){
public int compare(int[] interval1, int[] interval2){
return interval1[0] - interval2[0];
}
});
用Java写算法不可避免的会遇到这样的写法;
这里实际上就是运用的匿名内部类写法:
Java
new Comparator<>(){...逻辑...}
因为只需要用一次,所以不需要命名也就是匿名;
实现逻辑也是直接 <>()
这个其实有点像new int[]
TIP:Comparator是util包的,我们还有个Comparable是lang包的
他的compare函数则是:
java
public class Job implements Comparable<Job> {
private Runnable task;
private long startTime;
@Override
public int compareTo(Job o) {//传入一个参数和当前对比
return Long.compare(this.startTime, o.startTime);
}
}