Lambda表达式详解
Lambda表达式简介
Lambda表达式是JDK8引入的一种新特性,可以用来简化代码,使代码看上去更加优雅。
Lambda表达式格式
在Java中,我们想要将String数组按照字符串长度排序,常常需要这样做:
String[] plants = new String[]{"Mercury", "Venus", "Earth", "Mars", "Jupiter",
"Saturn", "Uranus", "Neptune"};
Arrays.sort(plants, new Comparator<String>() {
@Override
public int compare(String param1, String param2) {
return param1.length() - param2.length();
}
});
但是如果使用lambda表达式,可以简写成:
Arrays.sort(plants, (param1, param2) -> param1.length() - param2.length());
Lambda表达式由3个部分组成:参数、箭头、表达式。具体格式为(param) -> {表达式}
- 参数为空可以省略为
() -> {表达式}比如() -> {for (int i = 100; i >= 0;i-- ) System.out.println(i)}; - 参数不为空,但是可以推到出类型时,可以省略类型。比如上面的代码原式为
(String param1, String param2) -> {return param1.length() - param2.length()}也可以简写为
(String param1, String param2) -> {
return param1.length() - param2.length();
}
如果只有一个参数,也可以省略小括号。
ActionListener listener = event -> System.out.println("The time is " + new Date()");
- 方法体只有一条语句,可以省略
{}和return语句。
(String param1, String param2) -> param1.length() - param2.length();
上述几个条件一综合,就变成了我们最终看到的样子。
什么时候可以使用Lambda表达式
对于只有一个抽象方法的接口,需要使用这种接口的对象时,就可以提供一个lambda表达式。这种接口称为函数式接口(functional interface)。
java API中提供了许多非常通用的函数式接口。比如BiFunction<T, U, R>接口。我们可以把Comparator接口替换
BiFunction<String,String, Integer> biFunction = (param1, param2) -> param1.length()+param2.length();
不过我们会发现并没有能够接收BiFunction类型的方法。这是因为类似Comparator的接口往往有一个特定的用途,而不是只提供一个有指定参数和返回类型的方法。在ArrayList中有个removeIf方法,它的接收值就是Predicate类型,就是用来传递lambda表达式的。
public interface Predicate<T> {
boolean test(T t);
// Additional default and static methods
方法引用
有时,已经有方法可以完成你需要的操作了,可以在lambda表达式中直接指向你的方法:
Timer t = new Timer(1000, event -> System.out.println(event)):可以简化成Timer t = new Timer(1000, Systei.out::println) ;。表达式System.out::println是一个方法引用( method reference ), 它等价于lambda 表达式x 一> System.out.println(x)。更加简便的例子是如果你想对字符串进行不考虑大小写排序,Arrays.sort(strings, String::conpareToIgnoreCase)
方法引用有3种
• object::instanceMethod
• Class::staticMethod
• Class::instanceMethod
静态方法属于类名,普通方法属于对象。
构造器方法使用有点不同,构造器方法名称可以用new代替。比如Person::new
扩展
我们查看Runnable接口时,可以发现有这样一个注解@FunctionalInterface:
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
如果你自己设计一个接口,其中只有一个抽象方法时,就可以使用@FunctionalInterface标记。这样做有2个好处。如果你无意中增加了另一个抽象方法,编译期会产生一个错误。java doc中会指出你的接口是一个函数式接口。
浙公网安备 33010602011771号