• Java8新特性--函数式接口


    一. 函数式接口

    • 概念

      函数式接口在java中指的是:有且只有一个抽象方法的接口

    • @FunctionalInterface注解

      java8中专门为函数式接口引入一个新的注解,叫**@FunctionalInterface**,该注解用在接口的定义上

      比如:

      @FunctionalInterface
      public interface Animal {
          public abstract void eat();
          // public abstract void walk();
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5

      注意:一旦使用了这个FunctionalInterface注解定义接口,编译器就会检查接口是否有且只有一个抽象方法,没有满足的话就会报错。(但是即使没有使用这个注解,只要接口满足函数接口的要求,仍是一个函数接口,加这个注解只是帮助检查)

      FunctionalInterface.png

    • 关于接口中的static方法和default方法

      • static方法

        java8中接口可以定义一个或多个static方法,使用方法和普通static方法一样。

        注意:实现接口的类或者子接口是不会继承接口中的静态方法的

      • default方法

        java8在接口中新增的default定义方法,default默认方法不是抽象方法,不会影响函数接口的判断。

        定义的default方法,子接口或实现类可以不需要实现,直接调用,也可以重写这个default定义的方法(重写时候不需要加default关键字)。

      注意:函数式接口中有且只能有一个抽象方法,但可以有多个static方法或default方法。

    二. 常用函数式接口

    常用的函数式接口主要在包java.util.function中提供,主要有以下几种常用接口。

    1. Supplier–供给型接口

      • 抽象方法

        T get():返回指定泛型的数据

        由于Supplier是一个函数式接口,意味着使用Lambda表达式时需要供给一个符合泛型类型的对象数据。

      import java.util.function.Supplier;
      
      public class FunctionInterfaceDemo {
          public static void main(String[] args) {
              String str1 = "Hello";
              String str2 = "Java";
      
              String s = strConcat(()-> str1 + str2);
              System.out.println(s);
          }
          
          // 拼接字符串
          public static String strConcat(Supplier<String> supplier) {
              return supplier.get();
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

      其实就是使用函数式接口作为函数参数,调用时使用Lambda表达式实现函数式接口的抽象方法。

      而Supplier的抽象方法get是返回一个泛型类型的数据对象,这里是String,所以返回一个String。

    2. Consumer–消费型接口

      • 抽象方法

        void accept(T t):对给定的参数执行此操作(消费数据t)

      • 默认方法

        default Consumer andThen(Consumer after):组合消费,先执行调用andThen接口的对象的accept方法,再执行after中的accept方法。

      accept()使用实例:

      import java.util.function.Consumer;;
      
      public class FunctionInterfaceDemo {
          public static void main(String[] args) {
              String str = "Hello World";
              consumeStr(str, (s) -> System.out.print(s));
          }
          // 消费字符串
          public static void consumeStr(String str, Consumer<String> consumer) {
              consumer.accept(str);
          } 
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12

      andThen()使用实例:

      import java.util.function.Consumer;;
      
      public class FunctionInterfaceDemo {
          public static void main(String[] args) {
              String str = "Hello World";
              consumeStr(str, 
                      (s) -> System.out.println(s.toUpperCase()),
                      (s) -> System.out.println(s.toLowerCase()));
          }
          // 消费字符串,先变大写,再变小写
          public static void consumeStr(String str, Consumer<String> con1, Consumer<String> con2) {
              con1.andThen(con2).accept(str);
          } 
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
    3. Predicate–断言型接口

      • 抽象方法

        boolean Test(T t):传入一个参数,返回一个布尔值

      • 默认方法

        • default Predicate and(Predicate other):相当于逻辑运算中的与&&,当两个Predicate函数返回结果都是true时才返回true。
        • default Predicate or(Predicate other):相当于逻辑运算中的或||,当两个Predicate函数返回结果有一个为true,则返回true,否则返回false。
        • default Predicate negate():相当于逻辑运算中的!,就是取反的意思。

      test()实例:

      import java.util.function.Predicate;;;
      
      public class FunctionInterfaceDemo {
          public static void main(String[] args) {
             Predicate<Integer> predicate1 = (t) -> t > 0;
             // 执行test方法,会将参数10 进行 t>0 判断,结果返回true
             System.out.println(predicate1.test(10));
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9

      and(),or(),negate()实例:

      import java.util.function.Predicate;;;
      
      public class FunctionInterfaceDemo {
          public static void main(String[] args) {
              /**
               * 两个条件同时成立:
               * 1. 字符串长度大于5
               * 2. 以'A'开头
               */
              String[] array = {"Hello", "Air", "Apple", "Another"};
              Predicate<String> pre1 = (t) -> t.length() > 5;
              Predicate<String> pre2 = (t) -> t.startsWith("A");
              for (String s : array) {
                  if(pre1.and(pre2).test(s) == true) {
                      System.out.println(s);
                  }
              } // 输出Another
              System.out.println("---------------");
              /**
               * 只要有一个条件成立:
               * 1. 字符串长度大于5
               * 2. 以'A'开头
               */
              for (String s : array) {
                  if(pre1.or(pre2).test(s) == true) {
                      System.out.println(s);
                  }
              } // 输出Air,Apple,Another
              System.out.println("---------------");
              /**
               * 取反:
               * 1. 字符串长度大于5
               */
              for (String s : array) {
                  if(pre1.negate().test(s) == true) {
                      System.out.println(s);
                  }
              } // 输出Hello,Air,Apple
          }
       
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
    4. Function–函数型接口

      该接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。

      • 抽象方法

        R accept(T t):根据类型T的参数获取参数类型R的结果。

      • 默认方法

        • default Function andThen(Function after):组合操作,先执行调用andThen函数的对象的apply方法,然后再执行参数after中的apply方法。
        • default Function compose(Function before):与andThen相反,先调用before中的apply方法,再调用执行compose方法的对象中的apply方法。
      import java.util.function.Function;
      
      public class FunctionInterfaceDemo {
          public static void main(String[] args) {
              Function<Integer, Integer> func = (t) -> t * 2;
              System.out.println(func.apply(8));  // 输出 16
              System.out.println("------------");
      
              Function<Integer,Integer> fun1 = (t) -> t * t;
              Function<Integer,Integer> fun2 = (t) -> t + 2;
              // andThen和compose是相反的操作,相同的参数,结果完全不一样
              System.out.println(fun1.andThen(fun2).apply(8));    // 输出 66
              System.out.println(fun1.compose(fun2).apply(8));    // 输出 100
          }
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
  • 相关阅读:
    Effective Cpp
    MySQL视图详解
    Python中利用SQLAlchemy模块操作MySQL数据库
    离线数仓同步数据1
    实验二-----数据库
    xcode打包macos报错:FlutterInputs.xcfilelist 和 FlutterOutputs.xcfilelist
    多源最短路径算法:Floyd-Warshall算法分析
    Unity SKFramework框架(二十二)、Runtime Console 运行时调试工具
    基于樽海鞘群算法的线性规划求解matlab程序
    为什么红黑树的效率比较高?
  • 原文地址:https://blog.csdn.net/chisuisi5702/article/details/126284816