函数式接口

引言

在java中是指:有且仅有一个抽象方法的接口。当然接口中也可以有其他方法(默认、静态、私有)
Java8所有的新特性基本基于函数式编程的思想,函数式编程的带来,给Java注入了新鲜的活力。函数式编程的几个特点:

  1. 函数可以作为变量、参数、返回值和数据类型。
  2. 基于表达式来替代方法的调用
  3. 函数无状态,可以并发和独立使用
  4. 函数无副作用,不会修改外部的变量
  5. 函数结果确定性;同样的输入,必然会有同样的结果。
  6. 函数式接口,即适用于函数式编程场景的接口。而java中的函数式编程体现就是Lambda,所以函数式接口就是可 以适用于Lambda使用的接口。只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行推导。

@FunctionalInterface注解

作用:可以检测接口是否是一个函数式接口
是:编译成功
否:编译失败(接口中没有抽象方法或者抽象方法个数大于1)

函数式编程

有些场景的代码执行后,结果不一定会被使用,从而造成性能浪费。而Lambda表达式是延迟执行的,这正好可以 作为解决方案,提升性能。

public class Demo01 {
     public static void show(MyFunctionalInterface myInter){
         myInter.method();
  }
     public static void main(String[] args) {
         //调用show方法,方法的参数是一个接口,所以可以传递接口的实现类对象
         show(new MyFunctionalInterfaceImpl());
         //调用show方法,方法的参数是一个接口,所以我们可以传递接口的匿名内部类
         //out文件夹中会产生一个Demo01$1.class文件
         show(new MyFunctionalInterface() {
             @Override
             public void method() {
                 System.out.println("使用匿名内部类重写接口中的抽象方法");
             }
         });
         //调用show方法,方法的参数是一个函数式接口,所以我们可以使用Lambda表达式
         //不会产生.class文件
         show(()->{
             System.out.println("使用Lambda表达式重写接口中的抽象方法");
         });
         //简化Lambda表达式
         show(()->System.out.println("使用简化Lambda表达式重写接口中的抽象方法"));
     }
}

从应用层面来讲,Java中的Lambda可以被当做是匿名内部 类的“语法糖”,但是二者在原理上是不同的。 (Lambda表达式不会产生.class文件)

常用的函数式编程

JDK提供了大量常用的函数式接口以丰富Lambda的典型使用场景,它们主要在 java.util.function包中被提供。

Supplier接口

java.util.function.Supplier 接口仅包含一个无参的方法: T get()。用来获取一个泛型参数指定类型的对象数据。
Supplier接口被称之为生成型接口,指定接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据。

public class Demo01Supplier {
     public static String getString(Supplier<String> sp){
         return sp.get();
     }
     public static void main(String[] args) {
         //调用getString方法,参数Supplier<String>是一个函数式接口,所以可以用lambda表达式
         String s=getString(()->{return "hello World";});
         System.out.println(s);
         //优化lambda表达式
         String s1=getString(()->"hello world");
                  System.out.println(s);
     }
 }

Consumer接口

java.util.function.Consumer<T>接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据, 其数据类型由泛型决定。
泛型指定什么类型,就可以使用accept方法消费什么类型的数据,至于怎么消费,需要自定义(输出,计算…)

public class Demo01Consumer {
     public static void method(String name, Consumer<String>con){
         con.accept(name);
     }
     public static void main(String[] args) {
         method("李小明",(name)->{
             //消费方式:把字符串进行翻转输出
             StringBuffer reName=new StringBuffer(name).reverse();
             System.out.println(reName);
         });
     }
 }

还有一个值得注意的是他的andThen方法,它是它是Consumer接口的默认方法

作用:需要两个Consumer接口,可以把两个Consumer接口组合到一起,对数据进行消费

 Consumer<String> con1;
 Consumer<String> con2;
 String s="hello";
 con1.accept(s);
 con2.accept(s);//s被消费了两次
//连接两个Consumer接口,再进行消费,谁写下前面谁先消费
 con1.andThen(con2).accept(s);

Predicate接口

java.util.function.Predicate<T>接口。
作用:对某种数据类型的数据进行判断,结果返回一个boolean值
Predicate接口中包含一个抽象方法:
Boolean test(T t): 对指定数据类型的数据进行判断

public class Demo01Predicate {
     public static boolean checkString(String s,Predicate<String> pre){
         return pre.test(s);
     }
 
     public static void main(String[] args) {
         String s="sdffds";
         //调用checkString方法对字符串进行校验,参数传递字符串和Lambda表达式
 //        boolean b = checkString(s, (str) -> {
 //            //判断字符串的长度是否大于5
 //            return str.length()>5;
 //        });
         //优化lambda表达式
         boolean b = checkString(s, str -> str.length()>5);
         System.out.println(b);
     }
}

Predicate接口中三种默认方法and,or,negate(分别具有与或非的作用)分别在接口函数使用:

public static boolean checkString(String s,Predicate<String> pre1,Predicate<String> pre2){
        return pre1.and(pre2).test(s);//与方法
 public static boolean checkString(String s,Predicate<String> pre1,Predicate<String> pre2){
        return pre1.or(pre2).test(s);//或方法
public static boolean checkString(String s,Predicate<String> pre){
        return pre.negate().test(s);//取反方法

Function接口

java.util.function.Function<T,R> 接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。(相当于数学中y=f(x),称x->y的映射)
Function接口最主要的抽象方法为:R apply(T t),根据类型T的参数获取类型R的结果,使用场景例如:将String类型转换为Integer类型。
Function接口的默认方法andThen:用来进行组合操作。
下面是使用Function进行函数拼接,将字符串中的数字字符串先转换成integer型,在将其+100,最后输出。

 public class Demo03FunctionPractice {
     public static int change(String s,
                              Function<String,String> fun1,
                              Function<String,Integer>fun2,
                              Function<Integer,Integer>fun3)
     {
         int  result = fun1.andThen(fun2).andThen(fun3).apply(s);
         return result;
     }
     public static void main(String[] args) {
         String str="小明,18";
         int result = change(str,
                 (String s) ->
                 {
                     return s.split(",")[1];
                 },
                 (String s) ->
                 {
                     return Integer.parseInt(s);
 
                 },
                 (Integer i) ->
                 {
                     return i + 100;
                 });
         System.out.println(result);
     }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值