-
什么是lambda表达式
长期以来,java为了保持简单性和一致性,拒绝给变量赋值成“一段代码”,如果你想把“一段代码”赋给一个Java变量,应该怎么做呢?这个“一段代码”就是lambda表达式。
-
为什么引入lambda表达式
lambo表达式是一个可传递的代码块,具体介绍语法之前,先来看看我们在java中的哪些地方用过这种代码块。比如:
public static void main(String[] args) {
String[] planets = new String[] { "宋大宝", "大沈阳", "张三疯子", "腾", "夏洛特", "赵四","刘小能" };
Arrays.sort(planets, new Comparator<String>() {
@Override
public int compare(String first, String second) {
return first.length() - second.length();
}
});
System.out.println(Arrays.toString(planets));
}
这段代码大家应该很熟悉,是用sort方法传入一个Comparator对象进行list排序。
这其中有一个特点是构造出Comparator对象,compare包含一段代码来完成对“一段代码”的传递。
到目前为止,在java中传递一个代码段并不容易,不能直接传递代码段。java是一种面向对象语言,所以必须构造一个对象。这个对象的类需要有一个方法能包含所需的代码。
-
lambda表达式的语法
再来考虑上面讨论排序的例子。我们传入代码来检查一个字符串是否比另一个字符串短。这里要计算:
first.length() - second.length()
first和second是什么?他们都是字符串。java是一种强类型语言,所以我们还要指定它们的类型:
(String first, String second)
-> first.length() - second.length()
这就是你看到的第一个lambda表达式。lambda表达式就是一个代码块,以及必须传入代码的变量规范。
至此,我们可以看出lambda表达式形式:
(参数) -> 一个表达式或一段代码
如果想传入的代码很多无法放在一个表达式中,就可以像写方法一样,把这些代码放在{}中,并包含显示的return语句。例如:
(String first, String second) ->
{
if(first.length() < second.length()) return -1;
else if(first.length() > second.length()) return 1;
else return 0;
}
如果没有参数怎么办?仍然要提供空括号,就像无参数方法一样:
() -> { for(int i = 100; i>=0; i++) System.out.println(i); }
如果可以推导出一个lambda表达式的参数类型,则可以忽略其类型。例如:
Comparator<String> comp = (first, second) -> first.length - second.length;
在这里,编译器可以推导出first和second必然是字符串。因为lambda表达式将赋给一个字符串比较器。
如果方法只有一个参数,而且这个参数的类型可以推导得出。那么甚至还可以省略小括号:
Timer t = new Timer(1000, event ->
System.out.println("The time is:" + new Date()));
实例代码:
package com.lambda;
import java.util.Arrays;
import java.util.Date;
import javax.swing.JOptionPane;
import javax.swing.Timer;
public class LambdaTest {
public static void main(String[] args) {
String[] planets = new String[] { "宋大宝", "大沈阳", "张三疯子", "腾", "夏洛特", "赵四", "刘小能" };
System.out.println(Arrays.toString(planets));
System.out.println("排序:");
Arrays.sort(planets);
System.out.println(Arrays.toString(planets));
System.out.println("根据长度排序:");
Arrays.sort(planets, (first, second) -> first.length() - second.length());
System.out.println(Arrays.toString(planets));
Timer t = new Timer(1000, event ->
System.out.println("The time is:" + new Date()));
t.start();
JOptionPane.showMessageDialog(null, "退出?");
System.exit(0);
}
}
-
ArrayList的removeIf方法
试想如果当前我们需要清除list中所有null值,可以有如下写法:
List<String> list = new ArrayList<String>();
list.add("宋大宝");
list.add("大沈阳");
list.add(null);
System.out.println("初始时:"+ list.toString());
for(int i=0;i<list.size();i++) {
if(list.get(i) == null) {
list.remove(i);
}
}
System.out.println("过滤完:" + list.toString());
java1.8的ArrayList新增了一个removeIf方法,一行代码搞定:
list.removeIf(e -> e == null);
removeIf方法的参数是一个Predicate接口。这个接口专门用来传递lambda表达式:
public interface Predicate < T >
{
boolean test ( T t ) ;
// Additional default and static methods
}