使用Lambda表达式的前提是有函数式接口,而Lambda表达式使用时不关心接口名,抽象方法名。只关心抽象方法的参数列表和返回值类型,因此为了更加方便的使用Lambda表达式,JDK提供了大量常用的函数式接口(java.util.function包下)。其实JDK提高函数式接口就是为了方便开发者,无需开发者再去定义函数式接口了,下面介绍四种常用的函数式接口。

Supplier函数式接口

  1. @FunctionalInterface
  2. public interface Supplier<T> {
  3. /**
  4. * Gets a result.
  5. *
  6. * @return a result
  7. */
  8. T get();
  9. }

通过源码可知,Suppler函数式接口没有参数,只有返回值,用于生成数据,比如:

  1. public class LambdaTest {
  2. public static void main(String[] args) {
  3. fun1(()->{
  4. int[] arr={10,22,78,3,56,43,29,75};
  5. Arrays.sort(arr);
  6. return arr[arr.length-1];
  7. });
  8. }
  9. private static void fun1(Supplier<Integer> supplier){
  10. Integer max = supplier.get();
  11. System.err.println("max = "+max);
  12. }
  13. }

image.png

Consumer函数式接口

  1. @FunctionalInterface
  2. public interface Consumer<T> {
  3. /**
  4. * Performs this operation on the given argument.
  5. *
  6. * @param t the input argument
  7. */
  8. void accept(T t);
  9. default Consumer<T> andThen(Consumer<? super T> after) {
  10. Objects.requireNonNull(after);
  11. return (T t) -> { accept(t); after.accept(t); };
  12. }
  13. }

通过源码可知,该函数式接口有参无返回值,用于消费数据,比如:

  1. public class LambdaTest {
  2. public static void main(String[] args) {
  3. fun2(msg -> {
  4. System.err.println(msg + " ---转换为大写--- " + msg.toUpperCase());
  5. });
  6. }
  7. private static void fun2(Consumer<String> consumer) {
  8. consumer.accept("consumer accept");
  9. }
  10. }

image.png
此外,该函数式接口还多了一个默认方法andThen,通过源码不难知道它是先执行Consumer t,再执行Consumer after,如:

  1. public class LambdaTest {
  2. public static void main(String[] args) {
  3. fun3(msg -> {
  4. System.err.println(msg + " ---转换为大写--- " + msg.toUpperCase());
  5. }, msg2 -> {
  6. System.err.println(msg2 + " ---转换成小写--- " + msg2.toLowerCase());
  7. });
  8. }
  9. private static void fun3(Consumer<String> c1, Consumer<String> c2) {
  10. String str = "consumer accept";
  11. //c1先执行,执行完毕再执行c2
  12. c1.andThen(c2).accept(str);
  13. }
  14. }

image.png

Function函数式接口

  1. @FunctionalInterface
  2. public interface Function<T, R> {
  3. /**
  4. * Applies this function to the given argument.
  5. *
  6. * @param t the function argument
  7. * @return the function result
  8. */
  9. R apply(T t);
  10. default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
  11. Objects.requireNonNull(before);
  12. return (V v) -> apply(before.apply(v));
  13. }
  14. default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
  15. Objects.requireNonNull(after);
  16. return (T t) -> after.apply(apply(t));
  17. }
  18. static <T> Function<T, T> identity() {
  19. return t -> t;
  20. }
  21. }

通过源码可知Function函数式接口有参有返回值,根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。比如:

public class LambdaTest {
    public static void main(String[] args) {
        fun4(msg -> {
            return Integer.parseInt(msg);
        });
    }

    private static void fun4(Function<String, Integer> function) {
        System.err.println(function.apply("123345"));
    }
}

image.png
其它默认函数和静态函数读源码不难理解,不再一一介绍。

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);

    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

可以看到,Predicate函数式接口输入数据,返回的是布尔值,其它静态方法和默认方法就是做的“&&”、“||”、“==”等操作,比如:

public class LambdaTest {
    public static void main(String[] args) {
        fun5(msg -> {
            return msg.length() > 20;
        });
    }

    private static void fun5(Predicate<String> p) {
        String str = "Hello World";
        boolean test = p.test(str);
        System.out.println(test);
    }
}

image.png