JDK8 - Lambda表达式(二)

2020-05-10  本文已影响0人  张明学

本篇主要介绍Lambda的使用以及方法引用 A::B 以及JDK主自带的:Function (构造型函数接口)、Consumer (消费型函数接口)、Predicate(判断型函数接口)、Supplier(供给型函数接口)

方法引用


方法引用分为普通方法引用和静态方法引用,普通方法引用为:对象名::方法,静态方法引用为:类::方法。它用在函数式接口的唯一抽象方法实现中。
定义一个普通的方法:

public class RandomNumImpl {
    /**
     * 产生一个随机数
     */
    public void buildNum() {
        Random random = new Random();
        System.out.println(random.nextInt(10));
    }
}

定义一个函数式接口Glue

@FunctionalInterface
public interface Glue {
    void print();
}

如果用Lamabe来表示一个函数式接口Glue的匿名实现类,并且print方法的实现还需要用到RandomNumImpl类,常用的写法是:

@Test
public void test2() {
    RandomNumImpl randomNum = new RandomNumImpl();
    Glue glue = () -> {
        randomNum.buildNum();
    };
    glue.print();
}

也可以简化成:

@Test
public void test3() {
    RandomNumImpl randomNum = new RandomNumImpl();
    Glue glue = randomNum::buildNum;
    glue.print();
}

如果把函数式接口Glue的唯一抽象方法print的实现改成需要调一个类的静态方法,还可以简化成:

public class RandomNumImpl {

    public static void buildLongNum() {
        Random random = new Random();
        System.out.println(random.nextLong());
    }

} 

@Test
public void test4() {
    Glue glue = RandomNumImpl::buildLongNum;
    glue.print();
}

*** 小结一下: A::B A表示Lamada将要实现的抽象方法所需外部变量名,B表示A的某个方法,如果是静态方法,A则为了类名。***

下面实战应用一下 A::B的写法。下面例子用到的Book类如下:

@Data
public class Book {

    private String name;

    private Double price;

    public Book() {

    }

    public Book(String argName) {
        this.name = argName;
    }

    public Book(String argName, Double argPrice) {
        this.name = argName;
        this.price = argPrice;
    }

    public void addPrice(Double argPrice){
        this.price = price + argPrice;
    }

    public static void goPage(Integer page) {
        System.out.println("goto page = " + page);
    }

    public boolean compare(Double argPrice){
        return this.price > argPrice;
    }

}

Function 构造型函数接口

作用:接收一个参数,返回一个对象。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);
    
}

以Book为例构造一个Function的Lambda表达式

    @Test
    public void testFunction1() {
        Function<String, Book> function = (name) -> {
            return new Book(name);
        };
        Book book = function.apply("JAVA");
        log.info(book.toString());
    }

JDK提供了一个新的写法:类::new 来简化上面的写法:

    @Test
    public void testFunction2() {
        Function<String, Book> function = Book::new;
        Book book = function.apply("JAVA");
        log.info(book.toString());
    }

使用 类::new 表示直接由类的构方法来实现Function接口中的apply方法,这个里有一个特殊之在于apply方法有一个参数,因此类必须要要有一个参数的构造方法

Consumer 消费型函数接口

作用:接收一个对象,自由完成对对象的使用。源码:

@FunctionalInterface
public interface Consumer<T> {

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

由类的普通方法构造一个Consumer的Lambda表达式

    @Test
    public void testConsumer1() {
        Consumer<Book> consumer = (argBook) -> {
            argBook.addPrice(10D);
        };

        Book book = new Book("Java", 60D);
        consumer.accept(book);
        log.info(book.toString());
    }

也可以使用 变量名A::普通方法名B 来实现Consumer,即为:Consumer的accept方法由变量A的方法B实现,要求A的B方法是:有参并无返回值

    @Test
    public void testConsumer2() {
        Book book = new Book("Java", 60D);

        Consumer<Double> consumer = book::addPrice;
        consumer.accept(10D);
        log.info(book.toString());
    }

由类的静态方法构造一个Consumer的Lambda表达式

    @Test
    public void testConsumer3() {
        Consumer<Integer> consumer = (page) -> {
            Book.goPage(page);
        };
        consumer.accept(100);
    }

使用 类名A::静态方法名B 来实现Consumer,即为:Consumer的accept方法由类名A的方法B实现。要求与普通方法一样,有参并无返回值

    @Test
    public void testConsumer4() {
        Consumer<Integer> consumer = Book::goPage;
        consumer.accept(200);
    }

传说中的:System.out::println

    @Test
    public void testConsumer5() {
        Consumer<String> consumer = System.out::println;
        consumer.accept("Hello Word");
    }

上面等于:

    @Test
    public void testConsumer6(){
        new Consumer(){
            
            @Override
            public void accept(Object o) {
                System.out.println(o);
            }
        }.accept("Hello Word");
    }

即用System.out类的println实现了Consumer接口的accept方法。

Predicate和Supplier其实就是对Consumer增强,有接收参数和返回值页
构造一个Predicate的Lambda表达式

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

构造一个Predicate的Lambda表达式

    @Test
    public void testPredicate1() {
        Predicate<Book> predicate = (argBook) -> {
            return argBook.getPrice() > 100;
        };

        Book book = new Book();
        book.setPrice(120.0);
        boolean bool = predicate.test(book);
        log.info("bool={}", bool);
    }

argBook.getPrice() > 100 是一个自由的实现,如果Book类用一个方法也是接收一个参数并且返回boolean,就可以用 ::
使用 变量名A::方法名B 来实现Predicate,即为:Predicate的test方法由变量A的方法B实现,要求A的B方法是:有参并有返回boolean

    @Test
    public void testPredicate2() {
        Book book = new Book();
        book.setPrice(120.0);

        Predicate<Double> predicate = book::compare;
        boolean bool = predicate.test(100D);
        log.info("bool={}", bool);
    }

Supplier

作用:无参,返回一个值。源码:

@FunctionalInterface
public interface Supplier<T> {

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

构造一个Supplier的Lambda表达式

    @Test
    public void testSupplier1() {
        Book book = new Book();
        book.setName("Spring");
        Supplier<String> supplier = () -> {
            return book.getName();
        };
        System.out.println(supplier.get());

    }

使用 变量名A::方法名B 来实现Supplier,即为:Supplier的get方法由变量A的方法B实现。要求A的B方法是:无参并有返回值

    @Test
    public void testSupplier2() {
        Book book = new Book();
        book.setName("Spring");
        Supplier<String> supplier = book::getName;
        System.out.println(supplier.get());
    }
上一篇下一篇

猜你喜欢

热点阅读