JDK8-1-Lambda表达式(3)-函数式接口
有且仅有一个抽象方法的接口称为函数式接口,上文 中 java.util.function.Predicate 接口就是一个函数式接口,Java 8中引入的函数式接口定义在 java.util.function 包下
java.util.function.Predicate
java.util.function.Predicate接口定义了一个名叫test的抽象方法,它接受泛型 T 对象,并返回一个boolean。
@FunctionalInterface
public interface Predicate<T> {
/**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
boolean test(T t);
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
//省略 。。。
}
java.util.function.Consumer
java.util.function.Consumer定义了一个名叫accept的抽象方法,它接受泛型 T 的对象,没有返回(void)。你如果需要访问类型T的对象,并对其执行某些操作,就可以使用这个接口。
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
//省略 。。。
}
java.util.function.Function
java.util.function.Function<T, R>接口定义了一个叫作apply的方法,它接受一个泛型 T 的对象,并返回一个泛型R的对象。如果你需要定义一个Lambda,将输入对象的信息映射到输出,就可以使用这个接口(比如提取苹果的重量,或把字符串映射为它的长度)。
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
//省略 。。。
}
以下代码表示将一个String列表映射到包含每个String长度的Integer列表:
// [7, 2, 6]
List<Integer> l = Arrays.asList("lambdas","in","action")
.stream()
.map((String s) -> s.length())
.collect(Collectors.toList());
java.util.function.Supplier
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
@FunctionalInterface
查看 Java 8 API 发现函数式接口都带有 @FunctionalInterface 注解,但要注意的是函数式接口的定义为有且仅有一个抽象方法的接口,所以申明一个函数式接口只要满足这个定义而并不一定要加上 @FunctionalInterface 注解。
需要注意的是这个标注用于表示该接口会设计成一个函数式接口。如果你用@FunctionalInterface定义了一个接口,而它却不是函数式接口的话,编译器将返回一个提示原因的错误。
如果接口中有其他方法,需要提供默认实现,如下:
default 方法(默认方法)
在前面的例子中我们使用了stream api,如下:
List<Apple> greenApples = apples.stream()
.filter(apple -> "green".equals(apple.getColor()))
.collect(Collectors.toList());
从Java API 中可知,stream 方法是 java.util.Collection 接口 1.8 新定义的,并且默认提供了实现,假设一下如果 JDK8 在接口中没有提供默认实现,那么升级JDK后依赖这个接口的第三方框架或者现有代码就会编译失败,可以说 default 方法 给接口设计者提供了一个扩充接口的方式,而不会破坏现有的代码。
/**
* Returns a sequential {@code Stream} with this collection as its source.
*
* <p>This method should be overridden when the {@link #spliterator()}
* method cannot return a spliterator that is {@code IMMUTABLE},
* {@code CONCURRENT}, or <em>late-binding</em>. (See {@link #spliterator()}
* for details.)
*
* @implSpec
* The default implementation creates a sequential {@code Stream} from the
* collection's {@code Spliterator}.
*
* @return a sequential {@code Stream} over the elements in this collection
* @since 1.8
*/
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}