lambda
函数式接口
函数式接口是只定义了一个方法的接口,可以被lambda 匿名函数表达: 函数式接口的抽象方法签名被称为函数描述符
public interface Comparator<T> { ←---- java.util.Comparator
int compare(T o1, T o2);
}
public interface Runnable { ←---- java.lang.Runnable
void run();
}
public interface ActionListener extends EventListener { ←---- java.awt.event.ActionListener
void actionPerformed(ActionEvent e);
}
public interface Callable<V> { ←---- java.util.concurrent.Callable
V call() throws Exception;
}
public interface PrivilegedAction<T> { ←---- java.security.PrivilegedAction
T run();
}
@FunctionalInterface
这个标注用于表示该接口会设计成一个函数式接口,因此对文档来说非常有用。此外,如果你用 @FunctionalInterface 定义了一个接口,而它不是函数式接口的话,编译器将返回一个提示原因的错误。例如,错误消息可能是 “Multiple non-overriding abstract methods found in interface Foo”,表明存在多个抽象方法。请注意,@FunctionalInterface 不是必需的,但对于为此设计的接口而言,使用它是比较好的做法。它就像是 @Override 标注表示方法被重写了。
函数式接口类型
predicate
java.util.function.Predicate
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
public <T> List<T> filter(List<T> list, Predicate<T> p) {
List<T> results = new ArrayList<>();
for(T t: list) {
if(p.test(t)) {
results.add(t);
}
}
return results;
}
Predicate<String> nonEmptyStringPredicate = (String s) -> !s.isEmpty();
List<String> nonEmpty = filter(listOfStrings, nonEmptyStringPredicate);
Consumer
java.util.function.Consumer
@FunctionalInterface
public interface Consumer<T>{
void accept(T t);
}
public <T> void forEach(List<T> list, Consumer<T> c){
for(T i: list){
c.accept(i);
}
}
forEach(
Arrays.asList(1,2,3,4,5),
(Integer i) -> System.out.println(i) ←---- Lambda 是Consumer中accept方法的实现
);
Function
java.util.function.Function
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
public <T, R> List<R> map(List<T> list, Function<T, R> f) {
List<R> result = new ArrayList<>();
for(T t: list) {
result.add(f.apply(t));
}
return result;
}
// [7, 2, 6]
List<Integer> l = map(
Arrays.asList(" Lambda s", "in", "action"),
(String s) -> s.length() ←---- Lambda 是Function接口的apply方法的实现
);
注: Java 类型要么是引用类型(比如 Byte、Integer、Object、 List ),要么是基本类型(比如 int 、double、byte、char)。但是泛型(比如 Consumer
常用的函数式接口
类型检查
java 会自动检查lambda 的上下文从而判断lambda 应该继承哪一个函数式接口
类型判断
Comparator<Apple> c =
(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()); ←---- 没有类型推断
Comparator<Apple> c =
(a1, a2) -> a1.getWeight().compareTo(a2.getWeight()); ←---- 有类型推断