List greenApples = filter(inventory,(Apple a) -> "green".equals(a.getColor()));
到底在哪里可以使用Lambda呢?可以在函数式接口上使用Lambda表达式。
在上面的代码中,可以把Lambda表达式作为第二个参数传给filter方法,因为它这里需要Predicate,而这是一个函数式接口。
Predicate仅仅定义了一个抽象方法:
public interface Predicate{
boolean test(T t);
}
函数式接口就是只定义一个抽象方法的接口。如下所示:
public interface Runnable{
void run();
}
public interface Callable{
V call();
}
public interface PrivilegedAction{
V run();
}
判断以下是否是函数式接口?
//符合函数式接口定义,属于函数式接口
public interface Adder{
int add(int a,int b);
}
//不是函数式接口,因为它定义了两个叫作add的抽象方法
public interface SmartAdder extends Adder{
int add(double a,double b);
}
//不是函数式接口,因为它没有声明抽象方法
public interface Nothing{
}
函数式接口可以干什么呢?Lambda表达式允许你直接以内联的形式为函数式接口的抽象方法提供实现,并把整个表达式作为函数式接口的实例(具体说来,是函数式接口一个具体实现的实例)。
用匿名内部类也可以完成同样的事情,只不过比较笨拙:需要提供一个实现,然后再直接将它实例化。
下面的代码是有效的,因为Runnable接口是一个只定义了一个抽象方法run的函数式接口:
Runnable r1 = () -> System.out.println("Hello World");
Runnable r2 = new Runnable(){
public void run(){
System.out.println("Hello World");
}
}
public static void process(Runnable r){
r.run();
}
process(r1);
process(r2);
//直接传递Lambda打印
process(() -> System.out.println("Hello World"));
函数式接口的抽象方法的签名基本上就是Lambda表达式的签名。我们将这种抽象方法叫作函数描述符。
() -> void 代表了参数列表为空,且返回void的函数。这正是Runnable接口所代表的。
(Apple,Apple) -> int 代表接受两个Apple作为参数且返回int的函数。
判断如下使用Lambda场景是否正确?
public void execute(Runnable r){
r.run();
}
//签名相同()->void,所以该场景下Lambda是有效的
execute(() -> {});
//该场景正确,因为Lambda签名与方法返回一致 () -> String
public Callable fetch(){
return () -> "Tricky example ;-";
}
//错误,签名不一致实际返回 (Apple)->int,而定义的是(Apple)->boolean
Predicate p = (Apple a) -> a.getWeight();