java8中预定义的函数式接口:Predicate、Consumer、Function等

上一篇中介绍的函数式接口的抽象方法是Lambda表达式的函数描述符,Lambda表达式需要有与之相匹配的函数式接口才能正常工作,那么在java8中,java的设计者为我们提供了哪些常用的函数式接口?

java.util.function.Predicate< T >

Predicate(谓词)函数式接口定义了一个test抽象方法,它接受泛型参数T并返回布尔值,其定义如下:

 
  1. @FunctionalInterface
  2. public interface Predicate<T>{
  3. boolean test(T t);
  4. }

谓词(predicate)在数学上常常用来代表一个类似函数的东西,它接受一个参数值,并返回true或false。

如果定义一个接受String对象的Lambda表达式,代码如下:

 
  1. //根据条件(行为)p过滤集合,符合条件p的加入过滤结果中
  2. public static <T> List<T> filter(List<T> list, Predicate<T> p) {
  3. List<T> results = new ArrayList<>();
  4. for(T s: list){
  5. if(p.test(s)){
  6. results.add(s);
  7. }
  8. }
  9. return results;
  10. }
  11. //Lambda表达式,判断非空
  12. Predicate<String> nonEmptyStringPredicate = (String s) -> !s.isEmpty();
  13. //从集合中过滤出非空的字符串
  14. List<String> nonEmpty = filter(listOfStrings, nonEmptyStringPredicate);

java.util.function.Consumer< T >

Consumer翻译成中文是“消费者”的意思,如果从输入输出的角度来考虑,消费这一行为有输入但没有输出,因为输入的东西被消费掉了,对应到java里的函数就是一个有参数但没有返回值的函数,这个函数就是函数式接口Consumer的抽象方法,方法名叫accept,接收一个泛型参数T,无返回(void),定义如下:

 
  1. @FunctionalInterface
  2. public interface Consumer<T>{
  3. void accept(T t);
  4. }

应用如下:

 
  1. public static <T> void forEach(List<T> list, Consumer<T> c){
  2. for(T i: list){
  3. c.accept(i);
  4. }
  5. }
  6. //Lambda是函数式接口Consumer中抽象方法accept的实现
  7. forEach(Arrays.asList(1,2,3,4,5),(Integer i) -> System.out.println(i));

这里传递给forEach方法的第二个参数:Lambda表达式,就相当于实现了函数式接口Consumer中抽象方法accept.

java.util.function.Function< T, R >

定义:

 
  1. @FunctionalInterface
  2. public interface Function<T, R>{
  3. R apply(T t);
  4. }

从函数式接口Function的定义中可以看出,抽象方法apply是将泛型参数对象T转换成了泛型R对象,常用于将输入信息映射成另一种类型的输出。示例如下:

 
  1.  
  2. public static <T, R> List<R> map(List<T> list,Function<T, R> f) {
  3. List<R> result = new ArrayList<>();
  4. for(T s: list){
  5. result.add(f.apply(s));
  6. }
  7. return result;
  8. }
  9. //将输入的字符串集合映射成字符串长度的整形集合
  10. List<Integer> l = map(Arrays.asList("lambdas","in","action"),(String s) -> s.length());

同样,上面代码传递给map方法的第二个参数:lambda表达式,是Function方法apply的实现。

原始类型特化

前方介绍的三个泛型函数式接口: Predicate< T >、 Consumer< T >和Function< T,R >,只能绑定到引用类型,对于基本类型,如int、double等,虽然也能使用包装类型Intger\Double等来解决,但会涉及到自动装箱操作,当处理一定量的数据时,会带来性能问题,因此java8针对原始类型特化了一些函数式接口,专门用来处理原始类型数据,避免装箱与拆箱带来的性能问题。如:IntPredicate、LongPredicate等,其使用跟普通的函数式接口一样,只是针对了特定的数据类型。

java8还预定义了其它类型的函数式接口,如Supplier(与Consumer相对应)、UnaryOperator等,将它们总结如下:

函数式接口函数描述符原始类型特化
Predicate< T >T->booleanIntPredicate,LongPredicate, DoublePredicate
Consumer< T >T->voidIntConsumer,LongConsumer, DoubleConsumer
Function< T,R >T->RIntFunction< R >,IntToDoubleFunction,IntToLongFunction,LongFunction< R >,LongToDoubleFunction,LongToIntFunction,DoubleFunction< R >,ToIntFunction< T >,ToDoubleFunction< T >,ToLongFunction< T >
Supplier< T >()->TBooleanSupplier,IntSupplier, LongSupplier,DoubleSupplier
UnaryOperator< T >T->TIntUnaryOperator,LongUnaryOperator,DoubleUnaryOperator
BinaryOperator< T >(T,T)->TIntBinaryOperator,LongBinaryOperator,DoubleBinaryOperator
BiPredicate< L,R >(L,R)->boolean 
BiConsumer< T,U >(T,U)->voidObjIntConsumer< T >,ObjLongConsumer< T >,ObjDoubleConsumer< T >
BiFunction< T,U,R >(T,U)->RToIntBiFunction< T,U >,ToLongBiFunction< T,U >,ToDoubleBiFunction< T,U >

一些常用的Lambda表达式与其对应的函数式接口应用举例:

使用案例Lambda表达式对应的函数式接口
布尔表达式(List list) -> list.isEmpty()Predicate< List< String > >
创建对象() -> new Apple(10)Supplier< Apple >
消费一个对象(Apple a) -> System.out.println(a.getWeight())Consumer< Apple >
从一个对象中选择/提取(String s) -> s.length()Function< String, Integer >或ToIntFunction< String >
合并两个值(int a, int b) -> a * bIntBinaryOperator
比较两个对象(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight())Comparator< Apple >或BiFunction< Apple, Apple, Integer > 或 ToIntBiFunction< Apple, Apple >
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值