Java函数式接口

  1. 介绍
    1. 概念
    2. 原理
    3. 格式
    4. @FunctionalInterface
      1. 使用
  • Supplier
    1. 接口
    2. 例子
  • Consumer
    1. 接口
      1. accept
      2. andThen
  • 例子
  • Predicate
    1. 接口
      1. test
      2. and
      3. or
      4. negate
  • 例子
  • Function
    1. 接口
      1. apply
      2. andThen
      3. compose
      4. identity
  • 例子
  • 介绍

    概念

    函数式接口,即适用于函数式编程场景的接口。而Java中的函数式编程体现就是Lambda,所以函数式接口就是可以适用于Lambda使用的接口。只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行推导。

    原理

    类似函数指针。
    通过生成一个私有静态方法和一个内部类后,在内部类中实现函数式接口,在实现接口的方法中,会滴哦啊用编译器生成的私有静态方法;调用lambda表达式的地方,通过传递内部类实现,来调用函数式接口方法。

    格式

    修饰符 interface 接口名称 {
    public abstract 返回值类型 方法名称(可选参数信息);
    // 其他非抽象方法内容
    ......
    }

    接口当中抽象方法的 public abstract 是可以省略。

    @FunctionalInterface

    Java 8中专门为函数式接口引入了一个新的注解: @FunctionalInterface 。

    @FunctionalInterface
    public interface MyFunctionalInterface {
    void method();
    }

    编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。虽然不能在函数式接口中定义多个方法,但可以定义默认方法、静态方法、定义java.lang.Object里的public方法。
    @FunctionalInterface
    public interface MyFunctionInterface<T> {
    public void print(T x);
    default void doSomeMoreWork(){
    // Method body
    }
    static void printHello(){
    System.out.println("Hello");
    }
    @Override
    boolean equals(Object obj);
    }

    使用
    @FunctionalInterface
    public interface MyFunctionInterface<T> {
    void print(T x);
    }

    public class Main {
    public static void main(String[] args) {
    method("a", (a) -> {
    System.out.println(a);
    });
    }

    private static void method(String arg, MyFunctionInterface<String> fun) {
    fun.print(arg);
    }
    }

    Supplier

    接口

    @FunctionalInterface
    public interface Supplier<T> {

    /**
    * Gets a result.
    *
    * @return a result
    */
    T get();
    }

    该函数式接口提供一个返回泛型数据的无参函数。

    例子

    public class Main {
    public static void main(String[] args) {
    String arg = testSupplier(() -> {
    return "testSupplier";
    });
    System.out.println(arg);
    }

    private static String testSupplier(Supplier<String> supplier) {
    return supplier.get();
    }
    }

    Consumer

    接口

    @FunctionalInterface
    public interface Consumer<T> {

    /**
    * Performs this operation on the given argument.
    *
    * @param t the input argument
    */
    void accept(T t);

    /**
    * Returns a composed {@code Consumer} that performs, in sequence, this
    * operation followed by the {@code after} operation. If performing either
    * operation throws an exception, it is relayed to the caller of the
    * composed operation. If performing this operation throws an exception,
    * the {@code after} operation will not be performed.
    *
    * @param after the operation to perform after this operation
    * @return a composed {@code Consumer} that performs in sequence this
    * operation followed by the {@code after} operation
    * @throws NullPointerException if {@code after} is null
    */
    default Consumer<T> andThen(Consumer<? super T> after) {
    Objects.requireNonNull(after);
    return (T t) -> { accept(t); after.accept(t); };
    }
    }

    提供了两个函数,和Supplier相反,获取一个参数。

    accept

    接收一个泛型参数。

    andThen

    完成多个Consumer的组合调用。
    注意:requireNonNull 静态方法将会在参数为null时主动抛出NullPointerException 异常。

    例子

    public class Main {
    public static void main(String[] args) {

    testConsumer(
    s1 -> {
    System.out.println("1:"+s1);
    },
    s2 -> {
    System.out.println("2:"+s2);
    },
    s3 -> {
    System.out.println("3:"+s3);
    }
    );
    }

    public static void testConsumer(Consumer<String> one, Consumer<String> two, Consumer<String> three) {
    one.andThen(two).andThen(three).accept("one");
    }
    }

    他将会按照顺序进行调用。

    Predicate

    接口

    @FunctionalInterface
    public interface Predicate<T> {

    /**
    * Evaluates this predicate on the given argument.
    *
    * @param t the input argument
    * @return {@code true} if the input argument matches the predicate,
    * otherwise {@code false}
    */
    boolean test(T t);

    /**
    * Returns a composed predicate that represents a short-circuiting logical
    * AND of this predicate and another. When evaluating the composed
    * predicate, if this predicate is {@code false}, then the {@code other}
    * predicate is not evaluated.
    *
    * <p>Any exceptions thrown during evaluation of either predicate are relayed
    * to the caller; if evaluation of this predicate throws an exception, the
    * {@code other} predicate will not be evaluated.
    *
    * @param other a predicate that will be logically-ANDed with this
    * predicate
    * @return a composed predicate that represents the short-circuiting logical
    * AND of this predicate and the {@code other} predicate
    * @throws NullPointerException if other is null
    */
    default Predicate<T> and(Predicate<? super T> other) {
    Objects.requireNonNull(other);
    return (t) -> test(t) && other.test(t);
    }

    /**
    * Returns a predicate that represents the logical negation of this
    * predicate.
    *
    * @return a predicate that represents the logical negation of this
    * predicate
    */
    default Predicate<T> negate() {
    return (t) -> !test(t);
    }

    /**
    * Returns a composed predicate that represents a short-circuiting logical
    * OR of this predicate and another. When evaluating the composed
    * predicate, if this predicate is {@code true}, then the {@code other}
    * predicate is not evaluated.
    *
    * <p>Any exceptions thrown during evaluation of either predicate are relayed
    * to the caller; if evaluation of this predicate throws an exception, the
    * {@code other} predicate will not be evaluated.
    *
    * @param other a predicate that will be logically-ORed with this
    * predicate
    * @return a composed predicate that represents the short-circuiting logical
    * OR of this predicate and the {@code other} predicate
    * @throws NullPointerException if other is null
    */
    default Predicate<T> or(Predicate<? super T> other) {
    Objects.requireNonNull(other);
    return (t) -> test(t) || other.test(t);
    }

    /**
    * Returns a predicate that tests if two arguments are equal according
    * to {@link Objects#equals(Object, Object)}.
    *
    * @param <T> the type of arguments to the predicate
    * @param targetRef the object reference with which to compare for equality,
    * which may be {@code null}
    * @return a predicate that tests if two arguments are equal according
    * to {@link Objects#equals(Object, Object)}
    */
    static <T> Predicate<T> isEqual(Object targetRef) {
    return (null == targetRef)
    ? Objects::isNull
    : object -> targetRef.equals(object);
    }
    }
    test

    抽象方法,接收一个泛型,并返回一个boolean类型。

    and

    后续跟随的操作,将会进行与(&&)操作

    or

    后续跟随的操作,将会进行或(||)操作

    negate

    后续跟随的操作,将会进行非(!)操作

    例子

    public class Main {
    public static void main(String[] args) {

    boolean test = testPredicate(
    s1 -> {
    System.out.println("1:" +s1);
    return true;
    },
    s2 -> {
    System.out.println("2:" +s2);
    return false;
    },
    s3 -> {
    System.out.println("3:" +s3);
    return false;
    }
    );
    System.out.println(test);
    }

    public static boolean testPredicate(Predicate<String> p1, Predicate<String> p2, Predicate<String> p3) {
    return p1.and(p2).or(p3).negate().test("AAA");
    }
    }

    Function

    接口

    @FunctionalInterface
    public interface Function<T, R> {

    /**
    * Applies this function to the given argument.
    *
    * @param t the function argument
    * @return the function result
    */
    R apply(T t);

    /**
    * Returns a composed function that first applies the {@code before}
    * function to its input, and then applies this function to the result.
    * If evaluation of either function throws an exception, it is relayed to
    * the caller of the composed function.
    *
    * @param <V> the type of input to the {@code before} function, and to the
    * composed function
    * @param before the function to apply before this function is applied
    * @return a composed function that first applies the {@code before}
    * function and then applies this function
    * @throws NullPointerException if before is null
    *
    * @see #andThen(Function)
    */
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
    Objects.requireNonNull(before);
    return (V v) -> apply(before.apply(v));
    }

    /**
    * Returns a composed function that first applies this function to
    * its input, and then applies the {@code after} function to the result.
    * If evaluation of either function throws an exception, it is relayed to
    * the caller of the composed function.
    *
    * @param <V> the type of output of the {@code after} function, and of the
    * composed function
    * @param after the function to apply after this function is applied
    * @return a composed function that first applies this function and then
    * applies the {@code after} function
    * @throws NullPointerException if after is null
    *
    * @see #compose(Function)
    */
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
    Objects.requireNonNull(after);
    return (T t) -> after.apply(apply(t));
    }

    /**
    * Returns a function that always returns its input argument.
    *
    * @param <T> the type of the input and output objects to the function
    * @return a function that always returns its input argument
    */
    static <T> Function<T, T> identity() {
    return t -> t;
    }
    }

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

    apply

    抽象方法,接收参数为泛型T,返回参数为泛型R

    andThen

    用来进行组合操作。

    compose

    提供一个前置泛型泛型V,完成将泛型V转为泛型T的前置工作。

    identity

    返回输入的泛型T参数。

    例子

    public class Main {
    public static void main(String[] args) {

    testFunction(
    s1 -> {
    System.out.println("1."+s1.getClass().getTypeName());
    return Double.parseDouble(s1.toString());
    },
    s2 -> {
    System.out.println("2."+s2.getClass().getTypeName());
    return s2.toString();
    },
    s3 -> {
    System.out.println("3."+s3.getClass().getTypeName());
    return Integer.parseInt(s3);
    }
    );

    }

    public static void testFunction(Function<Integer, Double> f1, Function<Double, String> f2, Function<String, Integer> f3) {
    f1.andThen(f2).compose(f3).apply("3");
    }
    }