阅读 122

Java8新特性学习-函数式接口

Java8新特性学习😝

Java大家庭已经出到11版本了,我还在使用jdk7=-=,再不学就来不及了,所以赶紧学一下Java8的新特性。


介绍

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口

函数式接口在java.util.function路径下。

在这个包中,每一个接口都被@FunctionalInterface标注,表示这个类是一个函数式接口,主要用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口定义的时候,编译器会报错。-- 摘录自菜鸟编程


具体使用

这次我们简单粗暴一下,贴出测试代码,看下具体使用场景和用法吧

在每个方法中都写上了注解

package com.example.demo;

import com.example.demo.test.Car;
import com.example.demo.test.PrintConsumer;
import org.junit.Test;

import java.util.Comparator;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.BinaryOperator;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.DoubleToIntFunction;
import java.util.function.Function;

/**
 * @author JingQ at 2019/1/25
 */
public class JDK8FunctionInterfaceTest {

    /**
     * BiConsumer<T, U>,接收两个参数,不返回结果(void)
     *
     * 输出:(说明函数内修改对象引用的话同时会修改对象的值)
     * 娃哈哈真好喝
     * TEST
     */
    @Test
    public void biConsumerTest() {
        BiConsumer<Car, String> biConsumer = (a, b) -> {
            System.out.println(a.getName() + b);
            a.setName("TEST");
        };
        Car car = new Car();
        car.setName("娃哈哈");
        biConsumer.accept(car, "真好喝");
        System.out.println(car.getName());
    }

    /**
     * BiFunction<T, U, R>, 接收两个参数<T, U>,返回R类型的结果
     * 输出:
     * 0 - 相等
     */
    @Test
    public void biFunctionTest() {
        BiFunction<Integer, Integer, String> biFunction = (a, b) -> String.valueOf(a+b);
        System.out.println(biFunction.apply(1, 2).compareTo("3"));
    }

    /**
     * BinaryOperator<T> 用来接收两个T类型的参数,返回T类型的结果
     */
    @Test
    public void binaryOperatorTest() {
        // 比较两者的最大值
        BinaryOperator<Integer> binaryOperator1 = BinaryOperator.maxBy(Comparator.naturalOrder());
        System.out.println(binaryOperator1.apply(1, 2));

        // 比较两者的最小值
        BinaryOperator<Integer> binaryOperator2 = BinaryOperator.minBy(Comparator.naturalOrder());
        System.out.println(binaryOperator2.apply(3, 4));

        // 相加
        BinaryOperator<Integer> add = (n1, n2) -> n1 + n2;
        System.out.println(add.apply(1, 3));
    }

    /**
     * BiPredicate<T, U>,接收两个参数<T, U>,返回一个boolean类型结果
     * 输出:
     * false
     */
    @Test
    public void biPredicateTest() {
        BiPredicate<Integer, Integer> biPredicate = (a, b) -> a.equals(b);
        System.out.println(biPredicate.test(1, 3));
    }

    /**
     * Boolean类型 提供者,用来获取一个Boolean值
     * 如果只是用来返回true/false,感觉这个方法比较鸡肋;感觉可以使用statement,在返回结果前执行
     */
    @Test
    public void booleanSupplierTest() {
        BooleanSupplier booleanSupplier = () -> {
            System.out.println("Pre Action");
            return Boolean.TRUE;
        };
        System.out.println(booleanSupplier.getAsBoolean());
    }

    /**
     * Consumer<T>,接受一个输入参数,返回空类型void
     * 还有一个andThen,可以用来实现责任链模式
     *
     * 输出:
     * TEST
     *
     * NEXT TEST
     * Pre
     * End
     */
    @Test
    public void consumerTest() {
        // 接受String类型的参数
        Consumer<String> consumer = System.out::println;
        consumer.accept("TEST");
        //空格预定
        System.out.println();
        // 责任链模式,可以设定下一个consumer
        //     PrintConsumer.java
        //      public void accept(String s) {
        //        System.out.println("Pre");
        //        //xxx
        //        System.out.println("End");
        //    }
        Consumer<String> nextConsumer = new PrintConsumer();
        consumer.andThen(nextConsumer).accept("NEXT TEST");
    }

    /**
     * DoubleToIntFunction 只有一个applyAsInt方法,接受double类型的参数,返回int类型的结果
     */
    @Test
    public void doubleToIntFunctionTest() {
        DoubleToIntFunction doubleToIntFunction = a -> (int) a;
        System.out.println(doubleToIntFunction.applyAsInt(10L));
    }

    /**
     * Function<T, U>函数接口,接受T类型的参数,返回U类型的结果
     *
     * compose和andThen这两个方法的区别在于执行方法的顺序问题
     *
     * compose先执行后面函数,然后执行前面的函数;andThen先执行前面的函数,然后再执行后面的函数
     */
    @Test
    public void functionTest() {
        // 方法引用,Integer[类名]::valueOf[方法名](这个是静态方法引用)
        Function<String, Integer> function1 = Integer::valueOf;
        System.out.println(function1.apply("1010"));
        // 输出 1010

        // andThen方法的入参类型为上一个方法的返回类型
        Function<Integer, String> function2 = a -> {
            System.out.println("Pre Action : ");
            return String.valueOf(a) + "10";
        };
        System.out.println(function1.andThen(function2).apply("1010"));
        //输出
        //Pre Action :
        //101010

        // compose方法
        Function<Integer, String> function3 = a -> {
            System.out.println(a);
            return a + "2020";
        };
        //compose先执行后面函数, 需要注意参数传递时调用的方法是否兼容,避免报错
        System.out.println(function1.compose(function3).apply(10));
        //输出
        //10
        //102020
    }

}

复制代码

小结

其它类型例如DoubleToLongFunction、IntSupplier之类的函数式接口,就是转换一下入参类型和出参类型,在用的时候查一下包下的API就能了解~


个人博客项目地址

希望各位帮忙点个star,给我加个小星星✨


参考资料

  1. Java 8 函数式接口
关注下面的标签,发现更多相似文章
评论