zoukankan      html  css  js  c++  java
  • JDK1.8 Consumer & Supplier 什么意思

    JDK1.8 函数式接口 Consumer & Supplier 以及 JAVA新纪元 λ表达式的到来

    背景什么的被吞了,直接进入主题


    函数式接口(定义自己百度,一大堆)

    因为看了一些关于JDK1.8函数式接口的文章,发现基本上都是糊里糊涂一笔带过.所以就抽空赶紧整理了一下.

    还是附上几个学习了解的传送门 :


    Consumer 函数式接口

    JDK 源码

    /**
     * 接受单个输入参数并且不返回结果的操作。
     * 与大多数其他功能接口不同, Consumer预期通过副作用进行操作。
     *
     * @since 1.8
     */
    @FunctionalInterface
    public interface Consumer<T> {
    
        /**
         * 对给定的参数执行此操作。
         *
         * @param t the input argument
         */
        void accept(T t);
    
        /**
         * 返回一个组合的Consumer ,依次执行此操作,然后执行after操作。 
         * 如果执行任一操作会抛出异常,它将被转发到组合操作的调用者。 
         * 如果执行此操作会引发异常,则不会执行after操作。
         *
         * @param 此操作后执行的操作
         * @return 一个组成的 Consumer ,依次执行 after操作
         * @throws NullPointerException - if after is null
         */
        default Consumer<T> andThen(Consumer<? super T> after) {
            Objects.requireNonNull(after);
            return (T t) -> { accept(t); after.accept(t); };
        }
    

    刚拿过来看的时候可能会有一些绕,但是我们换个角度来看一下.

    Consumer 直译过来就是消费者的意思,那我们是不是可以理解成消费代码.既然他要消费,那我们就要给他提供代码.

    来看一个简单的demo

    public void testConsumer1() {
            Consumer<String> consumer = new Consumer<String>() {
                @Override
                public void accept(String s) {
                    System.out.println(s + "?");
                }
            };
            consumer.accept("李磊");
        }

    输出结果

    李磊?

    简单解释一下

    Consumer是一个接口,所以当我们直接使用的话,要实现其 accept()方法,而这个方法的参数,就是我们定义接口时候给到的泛型,这里给的是一个String类型,方法当中的内容,就是我们所谓的消费代码,当调用accept()方法时执行.

    注意 : 也就是上面提到的通过副作用处理,我不清楚这个单词翻译的是否准确,看了很多博主和一些机器翻译都是这个意思,但我个人的理解意思,更趋近于说是通过侧面来解决问题.

    再看一下 consumer.accept("李磊")这一句,这里便是真正的执行的地方,也就是调用的我们刚刚自行实现的accept()方法.

    让我们继续刚刚的demo往下看

    这种写法和上面在JDK1.8环境中是等价的. 主要就是利用到了1.8中的 λ 表达式.

        public void testConsumer1() {
            Consumer<String> consumer = s -> System.out.println(s + "?");
            consumer.accept("李磊");
        }
    

    下面的例子均使用λ表达式完成

    泛型为自定义对象时

    public void testConsumerToSupplier() {
            Consumer<Person> consumer = person -> {
                person.setName("张颖");
                person.setSize(34);
            };
            Person person = new Person();
            consumer.accept(person);
            System.out.println("person = " + person);
        }
    

    输入结果:

    person = Person{name='张颖', size=34}

    泛型为自定义接口时

    public interface People {
        void come(Person person);
    }
    public void testConsumerAndInterfaceFunction() {
            Consumer<People> consumer = people -> {
                people.come(new Person("李四", 23));
                people.come(new Person("找钱", 34));
                people.come(new Person("孙俪", 45));
            };
    
            consumer.accept(this::print);
        }
    
        public void print(Person person) {
            System.out.println("person = " + person);
        }

    输出结果

    person = Person{name='李四', size=23}
    person = Person{name='找钱', size=34}
    person = Person{name='孙俪', size=45}

    如果到了这里还没有明白怎么回事,我建议你亲自动手敲上那么一遍.真的,如果还不懂来杭州,我当面给你讲.


    Supplier 函数式接口

    还是一样,先看一下JDK源码

    /**
     * 获得对象的一个函数式接口
     *
     * @since 1.8
     */
    @FunctionalInterface
    public interface Supplier<T> {
    
        /**
         * 得到一个对象
         *
         * @return 目标对象
         */
        T get();
    }
    

    这个是不是看起来很容易理解了,Supplier的意思是供应商,那我们是不是可以把他理解成一个商场,然后你告诉他你想要的东西是什么样子的,它是不是就会给你了.

    来看一下这个简单的demo

    void testSupplier1() {
            Supplier<String> supplier = () -> "这是你要的字符串";
            String str = supplier.get();
            System.out.println("str = " + str);
        }

    运行结果:

    str = 这是你要的字符串

    继续自定义对象

    void testSupplier2() {
            Supplier<Person> supplier = () -> {
                Person person = new Person();
                person.setName("张三");
                person.setSize(32);
                return person;
            };
    
            Person person = supplier.get();
            System.out.println("person = " + person);
        }

    运行结果

    person = Person{name='张三', size=32}

    再来刺激的自定义接口

        void testSupplier3() {
            Supplier<People> supplier = new Supplier<People>() {
                @Override
                public People get() {
                    People people = new People() {
                        @Override
                        public void come(Person person) {
                            System.out.println("person = " + person)
                        }
                    };
                    return people;
                }
            };
    
            People people = supplier.get();
            people.come(new Person("李四", 24));
        }
    

    输出结果

    person = Person{name='李四', size=24}

    看好别眨眼,λ表达式的写法 下面的一行和上面的一堆是等价的

    void testSupplier4() {
        Supplier<People> supplier = () -> person -> System.out.println("person = " + person);
        People people = supplier.get();
        people.come(new Person("李四", 24));
    }

    输出结果

    person = Person{name='李四', size=24}

    想必看到这你不光明白了 Supplier的用法,更清楚的λ表达式的用处了.


    写在最后,写这篇文章的原因是因为在整理工厂模式的时候遇到的一些问题

    工厂模式简单的是不能再简单了,但是随着技术的发展,也出现了一些新颖的工厂方法.CTS便是其中之一.

    至于Consumer&Supplier应用在工厂模式的代码如下,因为比较特殊,写在了一起,想要亲自体检复制粘贴运行TTT类的main()方法即可

    /**
     * @author lvgo
     * @version 1.0
     * @Description: CTS实现工厂模式
     * @date 18-8-24 下午3:57
     */
    public interface CTS {
    
        static CTS getCts(Consumer<Peoples> consumer) {
            Map<String, Supplier<Persons>> map = new HashMap<>();
            consumer.accept(map::put);
            return person -> map.get(person).get();
    
        }
    
        Persons getPerson(String name);
    }
    
    interface Peoples {
        void come(String name, Supplier<Persons> personSupplier);
    }
    
    class TTT {
        public static void main(String[] args) {
            CTS cts = CTS.getCts(people -> {
                people.come("张三", () -> new Persons("张三"));
                people.come("李四", () -> new Persons("李四"));
                people.come("王五", () -> new Persons("王五"));
            });
    
            Persons person = cts.getPerson("王五");
            System.out.println("persons = " + person);
        }
    }
    
    class Persons {
    
        private String name;
    
        public Persons() {
        }
    
        public Persons(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + "'}'";
        }
    }
    

    CTS工厂模式说明: Consumer To Supplier 自造词,无处可寻,他处偶遇纯属抄袭;

    通过Peoples接口的come()方法,可以动态在CTS工厂内添加person,然后使其具于生产该实例的能力.



    参考文献

  • 相关阅读:
    【洛谷P2014】选课【树形DP】【背包】
    【洛谷P2014】选课【树形DP】【背包】
    【洛谷P1939】【模板】矩阵加速(数列)
    【洛谷P1939】【模板】矩阵加速(数列)
    小X的液体混合【并查集】
    小X的液体混合【并查集】
    【JZOJ5914】盟主的忧虑【LCA】【并查集】【BFS】
    【JZOJ5914】盟主的忧虑【LCA】【并查集】【BFS】
    Silverlight 4:数据验证-今天的提示-第1部分
    酷的菜单按钮
  • 原文地址:https://www.cnblogs.com/lvgo/p/13275834.html
Copyright © 2011-2022 走看看