java8 API 函数式接口

简介

14年,Oracle公司如期发布了Java 8正式版,Java8提供了强大的流式处理及函数式接口编程
函数式接口编程,相信很多人在javascript中都使用过,比如回调函数,如今Java8也吸收了诸多的其它语言优点。

线程创建(8以前的写法)

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.printf(Thread.currentThread().getName());
            }
        });
        thread.start();

Java8的函数式接口写法


        //1Java8 lambda表达式写法
        Thread thread = new Thread(() -> {
            System.out.printf(Thread.currentThread().getName());
        });
        //对于{}里面只有一条语句的写法
        Thread thread1 = new Thread(() -> System.out.println(Thread.currentThread().getName()));

        //这种写法,不知道各位看官看着是什么感想
        Student student = new Student("yang", 2);
        new Thread(student::getName);

对比一下

        
        List<Student> list = new ArrayList<>();
        list.add(new Student("yang", 20));
        list.add(new Student("hehe", 25));
        list.add(new Student("jiana", 18));
        //对集合进行排序,以前的写法
        Collections.sort(list, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getAge() - o2.getAge();            }
        });

        //Java8 lambda表达式的写法
        Collections.sort(list, (o1, o2) -> o1.getAge()-o2.getAge());

Java8函数式编程可以使用lambda表达式,让代码更加简洁高效,当然对于许多如果刚接触的小伙伴来说,如果没有经过学习lambda式的写法,看起来也会云里雾里的,毕竟写法是高效了,但可读性确实要差一些了,对于改bug的同鞋来讲,难度是否又增加许多?

JDK 1.8 API包含了很多内建的函数式接口,在老Java中常用到的比如Comparator或者Runnable接口,这些接口都增加了@FunctionalInterface注解以便能用在lambda上。

标注为FunctionalInterface的接口被称为函数式接口,该接口只能有一个自定义方法,但是可以包括从object类继承而来的方法。如果一个接口只有一个方法,则编译器会认为这就是一个函数式接口。是否是一个函数式接口,需要注意的有以下几点:

1.该注解只能标记在”有且仅有一个抽象方法”的接口上。
2.JDK8接口中的静态方法和默认方法,都不算是抽象方法。
3.接口默认继承java.lang.Object,所以如果接口显示声明覆盖了Object中方法,那么也不算抽象方法。
4.该注解不是必须的,如果一个接口符合”函数式接口”定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错。
5.在一个接口中定义两个自定义的方法,就会产生Invalid ‘@FunctionalInterface’ annotation; FunctionalInterfaceTest is not a functional interface错误.

现如今,我们则从Function常用函数入口,真正了解一下。
1.Function:接受一个对象,返回一个对象

  /**
   * @param <T> the type of the input to the function
   * @param <R> the type of the result of the function
   * @since 1.8
   */
  @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);
  }

Function 内部有一个有一个apply(待子类实现)的方法,调用apply,回传R结果,通过泛型保证apply函数的入参入及返回值的类型。
基本使用:
对数据进行处理将String类型转换成double类型,代码如下:

        //先定义好这个函数功能
        Function<String, Double> stringToDouble = ((string) -> Double.parseDouble(string));

        //再使用函数功能
        System.out.println(stringToDouble.apply("20.25"));

异步回调处理

//将student的名字,通过回调的方式放入name变量中,name变量必须是Atomica类型的,因为交给别人,别人可以用线程来做
public class MainTest {
    public static void main(String[] args) {
        Student student2 = new Student("yanchuanbin", 25);
        AtomicReference<String> name = new AtomicReference<>("");
        String otherParams = "";
        new Operator(student2).handler(otherParams, (student) -> {
            System.out.println("here1 = " + Thread.currentThread().getName());
            name.set(student.getName());
            return null;
        });
    }
}
class Operator {
    Student student;
    public Operator(Student student) {
        this.student = student;
    }
    public void handler(String otherParams, Function<Student, Void> callback) {
        System.out.println("here2 = " + Thread.currentThread().getName());
        ThreadFactory threadFactory;
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.submit(() -> callback.apply(student));
    }
}

输出

here2 = main
here1 = pool-1-thread-1

2.Supplier:生产者,无参数,只有返回值
Supplier生产者,提前定义好生产方法,通过get()获取返回值,源码如下

@FunctionalInterface
public interface Supplier<T> {

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

作为生产者,基本使用

//        Supplier<Student> supplier2 = new Supplier() {
//            @Override
//            public Student get() {
//                return new Student("aa",new Random().nextInt(20);
//            }
//        };
        Supplier<Student> supplier = () -> new Student("yanchuanbin", 2);
        Student student = supplier.get();

3.Consumer:消费者,有入参,但无返回值
Consumer消费者,传入一个参数,消费后无返回值,源码如下

@FunctionalInterface
public interface Consumer<T> {

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

基本使用

        Student student = new Student("yanchuanbin", 25);
        //旧写法
//        Consumer<Student> consumer = new Consumer<Student>() {
//            @Override
//            public void accept(Student student) {
//                System.out.println(student.getAge());
//            }
//        };
        //lambad写法
        Consumer<Student> consumer = (student1 -> System.out.println(student1.getAge()));
        consumer.accept(student);

4.Predicate:断言,有参数T,返回固定类型boolean
断言式接口其参数是<T,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);

基本使用

     Predicate<Student> studentEqualsPredicate = (student) -> student.getAge() > 10;
     Student student = new Student("yanchuanbin", 25);
     System.out.println(studentEqualsPredicate.test(student));

输出

true

5.UnaryOperator:接收T对象,返回T对象
对对象进行处理,处理后,将原来的对象返回,入参和返回值都是T,源码如下:

@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
    /**
     * Returns a unary operator that always returns its input argument.
     * @param <T> the type of the input and output of the operator
     * @return a unary operator that always returns its input argument
     */
    static <T> UnaryOperator<T> identity() {
        return t -> t;
    }
}

基本使用

     UnaryOperator<Student> identity = (x -> {
            return new Student(x.getName(), x.getAge()+1);
     });
        
     //生产一个大一岁的哥出来,名字是一样的
     Student student1 = identity.apply(student);

6.BinaryOperator:传入两个T对象,返回T对象
继承自BiFunction,传入两个T类型的对象,返回一个T类型的对象,源码如下

   * @param <T> the type of the operands and result of the operator
   *
   * @see BiFunction
   * @see UnaryOperator
   * @since 1.8
   */
  @FunctionalInterface
  public interface BinaryOperator<T> extends BiFunction<T,T,T> {

BiFunction源码如下

@FunctionalInterface
public interface BiFunction<T, U, R> {
    /**
     * @param t the first function argument
     * @param u the second function argument
     * @return the function result
     */
    R apply(T t, U u);

基本使用

        //传入两个学生,返回两个学生中年龄较大的学生对象
        BinaryOperator<Student> getMaxAgeStudentHandler = 
                (student1, student2) -> student1.getAge() > student2.getAge() ? student1 : student2;
        
        Student student1 = new Student("ya",20);
        Student student2 = new Student("wa",25);
        
        Student maxAgeStudent = getMaxAgeStudentHandler.apply(student1,student2);
posted @ 2021-03-09 14:49  心若向阳花自开  阅读(334)  评论(1编辑  收藏  举报