Java内置的几个函数式接口的基本使用

  1. 相关类:SupplierConsumerPredicateFunction

  2. 什么是函数式接口

    • 有且只有一个抽象方法的接口被称作函数式接口
    • 函数式接口可以直接写成Lambda表达式
    • 函数式接口还可以写成方法引用的方式
    • 函数式接口对外展示的是一个规范,只需要满足这种规范即可成为其实现
    • 函数式接口可以类比为多态在函数式结构上的实现
    package com.yusian.function;
    
    import java.util.function.Supplier;
    
    /**
    * Supplier是一个函数式接口,返回任意类型数据,是一个容器
    * 他是对所有无参并返回一个对象的结构抽象,一切无参并返回对象的方法都可以成为他的实现
    * 这使得编程变得更加开放,可以想像是多态在函数式编程方式上的实现
    */
    public class SupplierDemo {
    
       public static void main(String[] args) {
           // 1、匿名内部类
           Supplier<Person> sup1 = new Supplier<Person>() {
               @Override
               public Person get() {
                   return new Person();
               }
           };
           Person p1 = sup1.get();
    
           // 2、Lambda表达式
           Supplier<Person> sup2 = () -> new Person();
           Person p2 = sup2.get();
    
           // 3、方法引用
           Supplier<Person> sup3 = Person::new;
           Person p3 = sup3.get();
    
           // 4、本地方法模拟
           Person p4 = supplier();
    
           // 5、只要满足函数式结构就可以
           Supplier<Person> sup5 = SupplierDemo::supplier;
           Person p5 = sup5.get();
    
           System.out.println(p1);
           System.out.println(p2);
           System.out.println(p3);
           System.out.println(p4);
           System.out.println(p5);
       }
    
       /**
        * 获取一个Person实例对象
        * @return Person
        */
       public static Person supplier() {
           return new Person();
       }
    }
    

  3. 内置函数式接口的应用
  • Supplier:提供者,该接口返回一个对象,以任何方式及任何身份返回一个对象,只要是无参数返回一个对象的任何方法都可以成为其实现;

  • Consumer:消费者,传入一个对象无返回值,提供一个对象,可以是任何形式的调用,“尽情消费”;

    Consumer中有一个andThen方法,这个方法会返回一个Consumer,有点绕

     package com.yusian.function;
    
     import java.util.function.Consumer;
    
     public class ConsumerDemo {
         public static void main(String[] args) {
             /*
              * 输出结果为:
              * Hello World
              * Hello World-1
              * Hello World-2
              */
             Consumer<String> con = System.out::println;
             con.andThen(str -> {
                 System.out.println(str + "-1");
             }).andThen(str -> {
                 System.out.println(str + "-2");
             }).accept("Hello World");
    
             /*
              * 换个形式来解释:
              * con1调用andThen方法,con2为参数得到的结果是一个Consumer
              * 得到的这个Consumer即不是con1也不是con2,是一个会先执行con1的accept方法再执行con2的
              * accept方法的Consumer
              * 可以简单的理解为返回的这个Consumer中accept方法是将con1和con2的accept方法按先后顺序
              * 调用
              * 同理:再调用andThen方法是新这个新的Consumer调用的,再将con3拉进来返回一个新的                
              * Consumer
              * 从表面上看一共是定义了4个Consumer,现实上一共出现的Consumer有7个,每调用一次andThen
              * 都会生成一个新的Consumer
              */
             Consumer<String> con1 = str -> System.out.println(str + "-1");
             Consumer<String> con2 = str -> System.out.println(str + "-2");
             Consumer<String> con3 = str -> System.out.println(str + "-3");
             Consumer<String> con4 = str -> System.out.println(str + "-4");
             con1.andThen(con2).andThen(con3).andThen(con4).accept("Java");
         }
     }
     ```
     执行结果:
    
    ```cmd
     Hello World
    Hello World-1
     Hello World-2
     Java-1
     Java-2
     Java-3
     Java-4
    
  • Predicate:断言,用于对传入对象的boolean判断,给你一个对象,你告诉我是否;
     package com.yusian.function;
    
     import java.util.ArrayList;
     import java.util.function.Predicate;
    
     public class PredicateDemo {
         public static void main(String[] args) {
             demo01();
         }
    
         // 过滤字符串数组中的特定元素,2个过滤条件可以通过2个Predicate实现
         private static void demo01() {
             // 过滤数组
             String[] array = {"xxxx,女", "yyyy,女", "zzzz,男", "xxx,女"};
             ArrayList<String> list = new ArrayList<>();
             Predicate<String> pre1 = str -> str.split(",")[0].length() == 4;
             Predicate<String> pre2 = str -> str.split(",")[1].equals("女");
             for (String s : array) {
                 if (filter(s, pre1, pre2)) list.add(s);
             }
             System.out.println(list);
         }
    
         private static boolean filter(String str, Predicate<String> pre1, Predicate<String> pre2) {
             return pre1.and(pre2).test(str);
         }
    
         private static void basic() {
    
             Predicate<String> pre1 = str -> str.endsWith("s");
             Predicate<String> pre2 = str -> str.length() > 3;
    
             boolean b1 = pre1.test("yes");
             System.out.println(b1);
    
             // or方法返回的是一个新的Predicate,这个Predicate将前一个Predicate与传入的这个Predicate中的两个test方法进行或运算
             boolean b2 = pre1.or(pre2).test("think");
             System.out.println(b2);
    
             // and方法返回的是一个新的Predicate,这个Predicate将前一个Predicate与传入的这个Predicate中的两个test方法进行与运算
             boolean b3 = pre1.and(pre2).test("this");
             System.out.println(b3);
    
             // negate方法返回一个新的Predicate,这个Predicate的test方法是对调用者的test方法取反
             boolean b4 = pre1.negate().test("yes");
             System.out.println(b4);
    
             // equal方法只是简单的==运算,可能是为了充实这个接口的功能吧
             boolean b5 = pre1.equals(pre2);
             System.out.println(b5);
         }
     }
    
  • Function:功能
     package com.yusian.function;
    
     import java.util.function.Function;
    
     public class FunctionDemo {
         public static void main(String[] args) {
             // 将字符串拼接"10"再转成数字
             Function<String, Integer> fun1 = str -> Integer.parseInt(str + "10");
             // 将数字+10再转成字符串
             Function<Integer, String> fun2 = n -> String.valueOf(n + 10);
    
             // andThen会执行前面的Function的apply,所以是12310+10 数字12320
             String ret1 = fun1.andThen(fun2).apply("123");
             System.out.println(ret1);
    
             // compose会先执行后面Function的apply,所以是133拼接"10" 字符串13310
             Integer ret2 = fun1.compose(fun2).apply(123);
             System.out.println(ret2);
         }
     }
    

Leave a Reply