美文网首页
JDK8 - Lambda表达式(二)

JDK8 - Lambda表达式(二)

作者: 张明学 | 来源:发表于2020-05-10 18:24 被阅读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());
        }
    

    相关文章

      网友评论

          本文标题:JDK8 - Lambda表达式(二)

          本文链接:https://www.haomeiwen.com/subject/uqtsnhtx.html