转自:https://blog.csdn.net/qq_33591903/article/details/102948344
快速理解 Consumer、Supplier、Predicate 与 Function
前言
这几个接口都处在java.util.function包下,Consumer(消费型),Supplier(供给型)、Predicate(判断型)与Function(转换型),暂时不理解他们的类型没关系。
Consumer
Consumer 是一个消费型的接口
先看 Consumer 接口的源码,有一个未实现的抽象方法,和一个默认方法(jdk1.8 之后,接口里面可以有默认方法和静态方法)。
1 | @FunctionalInterface |
我们只在意这个accept方法,接收一个泛型参数,不返回任何值。ok,我们来简单实现它
1 | Consumer<Integer> consumer=new Consumer<Integer>() { |
接下来我们使用 lambda 表达式来对此匿名内部类进行改写。此时该 lambda 的类型就是 Consumer 类型。
1 | consumer = i-> System.out.println(i); |
当然我们也可以使用方法引用
1 | consumer=System.out::println; |
在 Stream 类中,我们发现常用的 forEach 接口接收一个 Consumer 类型的参数,源码如下
1 | void forEach(Consumer<? super T> action); |
我们将 consumer 传入 forEach 中,来实现遍历集合的操作。
1 | List<Integer> list= Arrays.asList(1,2,3,4,5); |
Consumer 总结:
- Consumer 接口是一个消费型的接口,只要实现它的 accept 方法,就能作为消费者来输出信息。
- lambda、方法引用都可以是一个 Consumer 类型,因此他们可以作为 forEach 的参数,用来协助 Stream 输出信息。
- Consumer 还有很多变种,例如 IntConsumer、DoubleConsumer 与 LongConsumer 等,归根结底,这些变种其实只是指定了 Consumer 中的泛型而已,方法上并无变化。
Supplier
Supplier 是一个供给型的接口,我们可以无条件的从它这里获取东西。
1 | @FunctionalInterface |
我们不需要为 get 方法传入任何参数,就能获得一个结果
1 | Supplier<Double> supplier=()->new Random().nextDouble(); |
我们看看 Supplier 在 Optional 中的应用。
1 | public T orElseGet(Supplier<? extends T> other) { |
该方法接收 Supplier 类型的参数,当 Optional 内部的 value 不为空时,才会返回 Supplier 中的值。例如
1 | Optional<Double> optional=Optional.empty(); |
这必定返回 Supplier 中的随机值,因为 Optional.empty() 包含的值就是 null。
Supplier 总结:
- Supplier 是一个供给型的接口,其中的 get 方法用于返回一个值。
- Supplier 也有很多的变种,例如 IntSupplier、LongSupplier 与 BooleanSupplier 等
Predicate
Predicate 是一个判断型接口,看看它的源码。
1 | @FunctionalInterface |
1 | Predicate<Integer> predicate=i->i>5; |
很明显,输出是 false。等等,既然可以进行判断,那和 Stream.filter() 有没有关系呢?
1 | Stream<T> filter(Predicate<? super T> predicate); |
1 | List<Integer> list= Arrays.asList(1,2,3,4,5,6,7,8); |
很简单,输出是678。
Predicate 总结:
- Predicate 是一个判断型的接口,用一个 test 方法去测试传入的参数。
- 当然,Predicate 也有对应的变种。
Function
Function 是一个功能型的接口,用于将一种类型的数据转化为另外一种类型的数据。
1 | @FunctionalInterface |
重点关注它的 apply 方法,现在就去实现它,并将之传入进 Stream.map() 方法中试试。
1 | public class TestFunction { |
输出 12,可以看得出,Function 中的 apply 方法将 Student 类型的数据转化为对应 id 的 Integer 类型的数据。
Function 总结:
- Function 是一个转换型的接口,其中的 apply 可以将一种类型的数据转化成另外一种类型的数据。
- Function 的变种就更多了。
总结
首先只要记住这四个接口的类型,Consumer(消费型)、Supplier(供给型)、Predicate(判断型)与Function(转换型),再记住他们对应的抽象方法 Consumer(accpet)、Supplier(get)、Predicate(test) 与 Function(apply)。