背景
在使用idea的时候,idea会给出一些优化建议,例如:
点开后,会变成原本的语句:
为啥这两句话会等价呢,于是就研究研究了这个lambda表达式的一些基本的概念
概念
首先呢,lambda表达式使用要求jdk≥1.8。
lambda表达式是匿名方法,它提供了轻量级的语法,从而解决了匿名内部类带来的“高度问题”。
由参数列表、箭头符号->和函数体组成。函数体既可以是一个表达式,也可以是一个语句块。
例如:
() -> System.out.println("线程建立")
( x, y ) -> x + y
能干什么用呢,我的理解是,从效果上看,基本上等价于返回一个接口类,这个接口类只能有一个方法,方法的参数列表就是->前面的参数列表,后面就是这个方法的函数体。
例如,比较常见的创建一个线程并启动,一般是这么写:
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程建立");
}
}).start();
这里Thread构造函数需要传递一个Runnable接口类,Runnable接口类实际上就有一个唯一的方法,就是run。所以Runnable这个匿名类就可以改写为lambda表达式方法:
new Thread(() -> {
System.out.println("线程建立");
}).start();
另外还有个特性,如果方法块中只有一句话,可以把大括号和分号去掉
new Thread(() -> System.out.println("线程建立")).start();
于是我们就把上面六行代码缩减成一行了。很酷炫有没有。
进阶
简单介绍完后,下面先简单介绍下其他有用的点:
在JDK1.8中,List等集合类适配了一些配合lambda表达式的方法,比如forEach等,配合lambda表达式可以方便的进行一些遍历等操作
List<Integer> list = new ArrayList<Integer>();
for (int i = 1; i < 101; i++) {
list.add(i);
}
list.forEach(s -> System.out.println(s));
forEach定义在Iterable接口中
可以看到,有个accept方法(default关键字是JDK1.8特性,可以给接口添加默认方法,类似抽象类,这个以后再说,先不考虑default关键字标注的方法),
Consumer接口,只有一个方法,所以当我们调用list.forEach(s -> System.out.println(s));也就是相当于实现了一个匿名类,类实现了Consumer接口,类似下面的代码:
list.forEach(new Consumer<Integer>() {
@Override
public void accept(Integer s) {
System.out.println(s);
}
});
实际上发现,如果在方法中使用lambda表达式,需要参数的接口类,是函数式接口,通俗讲就是函数式接口(Functional Interface)就是一个具有一个方法的普通接口。
像
- java.lang.Runnable
- java.util.concurrent.Callable
- java.util.Comparator
- java.io.FileFilter
还有很多,jdk也增加了许多,可以参考Java 8 函数式接口。
回到本文开头,也就不难看出为啥这两个等价了
因为RowMapper只有一个方法,mapRow,所以也就可以看作为一个函数式接口,那么就可以用lambda表达式进行编写了,(result, i)->{...}
。
其他
lambda如果配合1.8新增的集合类的Stream,还可以更方便的处理集合类的需求,这个有机会再分享吧。
本人由于研究使用lambda表达式时间也不太长,如果有错误还希望指出来,共同进步哈~