JDK1.8 & 函数式接口

249 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情

什么是函数式接口

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
函数式接口可以被隐式转换为 lambda 表达式。
Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)上, 说到函数式接口那么这个注解 @FunctionalInterface是函数式借口所必须的。

我们定义一个函数式接口

@FunctionalInterface
interface GreetingService
{
    void sayMessage(String message);
}
public static void main(String[] args) {
    //1.8之前 使用的是匿内部类来处理
    sayMessageTo(new GreetingService() {
        @Override
        public void sayMessage(String message) {
            System.out.println("匿内部类 message = "+message);
        }
    });
    //这是 Lambda 来实现的
    sayMessageTo((me)->{
        System.out.println("Lambda message = " + me);
    });

}

public static void sayMessageTo(GreetingService greetingService){
    greetingService.sayMessage("helle");
}

输出结果

匿内部类 message = helle
Lambda message = helle

下面我们看看JDK 为我们提供的函数式接口

JDK为我们提供的函数式接口一般是在 java.util.function 包下

image.png

下面我们列举几个常用的

1. Supplier 无入参但是有返回值
@FunctionalInterface
public interface Supplier<T> {

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

使用如下:

public static void main(String[] args) {
    sayMessageTo(()->{
        //当然这里可以做一些计算处理这里只是演示就直接返回 100了
        return 100;
    });

}

public static void sayMessageTo(Supplier<Integer> greetingService){
      //get()抽象方法
    Integer integer = greetingService.get();
    System.out.println("integer = " + integer);
}

结果

integer = 100
2. Consumer 有入参无返回值 Consumer <T> 这里的T是指入参泛型

这里讲字符串转换成小写

public static void main(String[] args) {
    sayMessageTo((msg)->{
        String s = msg.toLowerCase(Locale.ROOT);
        System.out.println("s = " + s);
    });

}

public static void sayMessageTo(Consumer<String> consumer){
    String str="Java is the first";
    consumer.accept(str);
}

这里需要注意一个新特性 默认方法 andThen

default Consumer<T> andThen(Consumer<? super T> after) {
    Objects.requireNonNull(after);
    return (T t) -> { accept(t); after.accept(t); };
}

使用如下

public static void main(String[] args) {
    sayMessageTwo((msg)->{
        //转小写
        String s = msg.toLowerCase(Locale.ROOT);
        System.out.println("msg1 = " + s);
    },msg2->{
       // 转大写
        String s = msg2.toUpperCase();
        System.out.println("msg2 = " + s);
    });

}
public static void sayMessageTwo(Consumer<String> consumer,Consumer<String> consumer2){
    String str="Java is the first";
    consumer.accept(str);
    consumer2.accept(str);
    consumer.andThen(consumer2).accept(str);
}
msg1 = java is the first
msg2 = JAVA IS THE FIRST
3. 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));
    }
}

使用:


public static void main(String[] args) {
    sayMessageTwo((msg)->{
        return Integer.parseInt(msg);
    });
}
public static void sayMessageTwo(Function<String,Integer> f1){
    Integer apply = f1.apply("100");
    System.out.println("apply = " + apply);
}
apply = 100

默认方法 andThen

public static void main(String[] args) {

    sayMessageTwo((msg)->{
        return Integer.parseInt(msg);
    },msg2 ->{
        return msg2 *10;
    });
}
public static void sayMessageTwo(Function<String,Integer> f1, Function<Integer,Integer> f2){
    Integer apply = f1.andThen(f2).apply("100");
    System.out.println("apply = " + apply);
}

默认方法 compose

public static void main(String[] args) {
    sayMessageTwo((msg)->{
        return msg*msg;
    },msg2 ->{
        return msg2*5;
    });
    sayMessageAndThen((msg)->{
        return msg*msg;
    },msg2 ->{
        return msg2*5;
    });

}
public static void sayMessageTwo(Function<Integer,Integer> f1,Function<Integer,Integer> f2){
    /* * 1. 100 * 5 = 500  500 * 500 = 250000 */
    Integer apply = f1.compose(f2).apply(100);
    System.out.println("apply = " + apply);
}
public static void sayMessageAndThen(Function<Integer,Integer> f1,Function<Integer,Integer> f2){
/* * 1. 100 * 100 = 10000  5 * 10000 = 50000 */
    Integer apply = f1.andThen(f2).apply(100);
    System.out.println("applyThen = " + apply);
}
apply = 250000
applyThen = 50000

compose 方法和 andThen方法的区别就是:
A.compose(B) 以B的结果作为值传入去获取A的结果
A.andThen(B) 是先获取到A的结果作为参数 去获取B的结果

3. Predicate 有入参有返回值为 boolean类型
@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);
    }

使用:


public static void main(String[] args) {
    sayMessageTwo((msg)->{
        return msg>8;
    });

}
public static void sayMessageTwo(Predicate<Integer> predicate){
    boolean test = predicate.test(9);
    System.out.println("apply = " + test);
}
apply = true

默认方法 :and() 同时满足
     negate()不满足
     or() 有一个满足

ublic static void main(String[] args) {
    sayMessageTwo((msg)->{
        return msg>8;
    },msg2->{
        return msg2<8;
    });

}
public static void sayMessageTwo(Predicate<Integer> p1,Predicate<Integer> p2){
    boolean test = p1.and(p2).test(9);
    boolean test1 = p1.or(p2).test(9);
    boolean test2 = p1.negate().test(9);
    System.out.println("test = " + test);
    System.out.println("test1 = " + test1);
    System.out.println("test2 = " + test2);

}
test = false
test1 = true
test2 = false

静态方法:isEqual ()

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

使用:

public static void main(String[] args) {
    Predicate<Object> java = Predicate.isEqual("java");
    boolean test = java.test("C++");
    System.out.println("test = " + test);
}

结果:

test = false

基本常用的函数式接口就介绍到这啦 。。明天见🥰🥰🥰