精华内容
下载资源
问答
  • 主要介绍了深入理解java1.8之supplier,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 主要介绍了Java8 Supplier接口和Consumer接口原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 最新及原版Apple 供应商名单, 它详细列出了基于支出的前 200 家全球供应商,并概述了为我们的供应链提供服务的供应商地址, 值得大家查阅及参考!
  • 实用且完整的特斯拉供应商资格评估表格及填写说明, 这是Excel格式, 可以直接修改使用。
  • supplier selection standards

    2020-12-15 18:21:05
    supplier selection standards是一篇关于物流采购的参考,能让你全面了解与感悟supplier selection stan...该文档为supplier selection standards,是一份很不错的参考资料,具有较高参考价值,感兴趣的可以下载看看
  • Supplier Development Process

    2020-12-15 16:40:18
    这是一款整理发布的Supplier Development Process,适用于学习、借鉴、参考Supplier Developm...该文档为Supplier Development Process,是一份很不错的参考资料,具有较高参考价值,感兴趣的可以下载看看
  • 本供应商手册适用于直接向特斯拉供应零件和/或材料的供应商。 它可与相关行业标准一起工作,并阐明特斯拉的要求和期望。 特斯拉致力于成为世界一流的创新领导者,并为支持这一承诺,根据其卓越的运营和方法选择供应...
  • 主要介绍了Java函数式接口Supplier接口实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • Supplier survey form——US

    2020-12-15 20:11:24
    Supplier survey form——US以围绕物流采购为核心,以方便大家了解学习Supplier survey form——US为前提...该文档为Supplier survey form——US,是一份很不错的参考资料,具有较高参考价值,感兴趣的可以下载看看
  • JSON 供应商 创建这个小型服务器只是为了让我不必等待我的后端人员完成工作后端的交付。 我可以编码到 URL 并处理真实的 JSON 响应,甚至可以向后端人员发送我的模型的样子 建造 需要节点、mongo db(在本地运行)和...
  • Infor Supplier exchange Fuctions For version 11.0
  • 刚刚出来最新版2020供应商责任进展报告-英文版,本报告描述了苹果(Apple)在2019年将所有这些承诺付诸实施的工作。无论是帮助向100%可再生能源过渡,还是对数百万人进行工作场所权利的培训,我们都将我们的价值观应用...
  • Tesla Supplier Handbook(特斯拉供应商手册) BMS-0000051 Rev 6.pdf
  • SAPSRM (over view)SAP Supplier Relationship Management (Col92)
  • 最新版苹果供应链清单
  • 今天我们还讲讲Consumer、Supplier、Predicate、Function这几个接口的用法,在 Java8 的用法当中,这几个接口虽然没有明目张胆的使用,但是,却是润物细无声的。为什么这么说呢? 这几个接口都在 java.util.function...

    今天我们还讲讲Consumer、Supplier、Predicate、Function这几个接口的用法,在 Java8 的用法当中,这几个接口虽然没有明目张胆的使用,但是,却是润物细无声的。为什么这么说呢?

    这几个接口都在 java.util.function 包下的,分别是Consumer(消费型)、supplier(供给型)、predicate(谓词型)、function(功能性),相信有了后面的解释,你应该非常清楚这个接口的功能了。

    那么,下面,我们从具体的应用场景来讲讲这个接口的用法!

    1 Consumer接口

    从字面意思上我们就可以看得出啦,consumer接口就是一个消费型的接口,通过传入参数,然后输出值,就是这么简单,Java8 的一些方法看起来很抽象,其实,只要你理解了就觉得很好用,并且非常的简单。

    我们下面就先看一个例子,然后再来分析这个接口。

    1.1 Consumer实例

    /**
         * consumer接口测试
         */
        @Test
        public void test_Consumer() {
            //① 使用consumer接口实现方法
            Consumer<String> consumer = new Consumer<String>() {
    
                @Override
                public void accept(String s) {
                    System.out.println(s);
                }
            };
            Stream<String> stream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");
            stream.forEach(consumer);
    
            System.out.println("********************");
    
            //② 使用lambda表达式,forEach方法需要的就是一个Consumer接口
            stream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");
            Consumer<String> consumer1 = (s) -> System.out.println(s);//lambda表达式返回的就是一个Consumer接口
            stream.forEach(consumer1);
            //更直接的方式
            //stream.forEach((s) -> System.out.println(s));
            System.out.println("********************");
    
            //③ 使用方法引用,方法引用也是一个consumer
            stream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");
            Consumer consumer2 = System.out::println;
            stream.forEach(consumer);
            //更直接的方式
            //stream.forEach(System.out::println);
        }
    

    输出结果

    1.2 实例分析

    consumer接口分析

    在代码①中,我们直接创建 Consumer 接口,并且实现了一个名为 accept 的方法,这个方法就是这个接口的关键了。

    我们看一下 accept 方法;这个方法传入一个参数,不返回值。当我们发现 forEach 需要一个 Consumer 类型的参数的时候,传入之后,就可以输出对应的值了。

    ② lambda 表达式作为 consumer

    Consumer<String> consumer1 = (s) -> System.out.println(s);//lambda表达式返回的就是一个Consumer接口
    

    在上面的代码中,我们使用下面的 lambda 表达式作为 Consumer。仔细的看一下你会发现,lambda 表达式返回值就是一个 Consumer;所以,你也就能够理解为什么 forEach 方法可以使用 lamdda 表达式作为参数了吧。

    ③ 方法引用作为 consumer

    Consumer consumer2 = System.out::println;
    

    在上面的代码中,我们用了一个方法引用的方式作为一个 Consumer ,同时也可以传给 forEach 方法。

    1.3 其他 Consumer 接口

    除了上面使用的 Consumer 接口,还可以使用下面这些 Consumer 接口。
    IntConsumer、DoubleConsumer、LongConsumer、BiConsumer,使用方法和上面一样。

    1.4 Consumer 总结

    看完上面的实例我们可以总结为几点。

    ① Consumer是一个接口,并且只要实现一个 accept 方法,就可以作为一个**“消费者”**输出信息。
    ② 其实,lambda 表达式、方法引用的返回值都是 Consumer 类型,所以,他们能够作为 forEach 方法的参数,并且输出一个值。

    2 Supplier 接口

    Supplier 接口是一个供给型的接口,其实,说白了就是一个容器,可以用来存储数据,然后可以供其他方法使用的这么一个接口,是不是很明白了,如果还是不明白,看看下面的例子,一定彻底搞懂!

    2.1 Supplier实例

    **
         * Supplier接口测试,supplier相当一个容器或者变量,可以存储值
         */
        @Test
        public void test_Supplier() {
            //① 使用Supplier接口实现方法,只有一个get方法,无参数,返回一个值
            Supplier<Integer> supplier = new Supplier<Integer>() {
                @Override
                public Integer get() {
                    //返回一个随机值
                    return new Random().nextInt();
                }
            };
    
            System.out.println(supplier.get());
    
            System.out.println("********************");
    
            //② 使用lambda表达式,
            supplier = () -> new Random().nextInt();
            System.out.println(supplier.get());
            System.out.println("********************");
    
            //③ 使用方法引用
            Supplier<Double> supplier2 = Math::random;
            System.out.println(supplier2.get());
        }
    

    输出结果

    2.2 实例分析

    ① Supplier接口分析

    Supplier<Integer> supplier = new Supplier<Integer>() {
                @Override
                public Integer get() {
                    //返回一个随机值
                    return new Random().nextInt();
                }
            };
    

    看一下这段代码,我们通过创建一个 Supplier 对象,实现了一个 get 方法,这个方法无参数,返回一个值;所以,每次使用这个接口的时候都会返回一个值,并且保存在这个接口中,所以说是一个容器

    ② lambda表达式作为 Supplier

    //② 使用lambda表达式,
            supplier = () -> new Random().nextInt();
            System.out.println(supplier.get());
            System.out.println("********************");
    

    上面的这段代码,我们使用 lambda 表达式返回一个 Supplier类型的接口,然后,我们调用 get 方法就可以获取这个值了。

    ③ 方法引用作为 Supplier

    //③ 使用方法引用
            Supplier<Double> supplier2 = Math::random;
            System.out.println(supplier2.get());
    

    方法引用也是返回一个Supplier类型的接口。

    2.3 Supplier 实例2

    我们看完第一个实例之后,我们应该有一个了解了,下面再看一个。

    /**
         * Supplier接口测试2,使用需要Supplier的接口方法
         */
        @Test
        public void test_Supplier2() {
            Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
            //返回一个optional对象
            Optional<Integer> first = stream.filter(i -> i > 4)
                    .findFirst();
    
            //optional对象有需要Supplier接口的方法
            //orElse,如果first中存在数,就返回这个数,如果不存在,就放回传入的数
            System.out.println(first.orElse(1));
            System.out.println(first.orElse(7));
    
            System.out.println("********************");
    
            Supplier<Integer> supplier = new Supplier<Integer>() {
                @Override
                public Integer get() {
                    //返回一个随机值
                    return new Random().nextInt();
                }
            };
    
            //orElseGet,如果first中存在数,就返回这个数,如果不存在,就返回supplier返回的值
            System.out.println(first.orElseGet(supplier));
        }
    

    输出结果

    代码分析

    Optional<Integer> first = stream.filter(i -> i > 4)
                    .findFirst();
    

    使用这个方法获取到一个 Optional 对象,然后,在 Optional 对象中有 orElse 方法 和 orElseGet 是需要一个 Supplier 接口的。

    //optional对象有需要Supplier接口的方法
            //orElse,如果first中存在数,就返回这个数,如果不存在,就放回传入的数
            System.out.println(first.orElse(1));
            System.out.println(first.orElse(7));
    
            System.out.println("********************");
    
            Supplier<Integer> supplier = new Supplier<Integer>() {
                @Override
                public Integer get() {
                    //返回一个随机值
                    return new Random().nextInt();
                }
            };
    
            //orElseGet,如果first中存在数,就返回这个数,如果不存在,就返回supplier返回的值
            System.out.println(first.orElseGet(supplier));
    
    • orElse:如果first中存在数,就返回这个数,如果不存在,就放回传入的数
    • orElseGet:如果first中存在数,就返回这个数,如果不存在,就返回supplier返回的值

    2.4 其他 Supplier 接口

    除了上面使用的 Supplier 接口,还可以使用下面这些 Supplier 接口。
    IntSupplier 、DoubleSupplier 、LongSupplier 、BooleanSupplier,使用方法和上面一样。

    2.5 Supplier 总结

    ① Supplier 接口可以理解为一个容器,用于装数据的。
    ② Supplier 接口有一个 get 方法,可以返回值。

    3 Predicate 接口

    Predicate 接口是一个谓词型接口,其实,这个就是一个类似于 bool 类型的判断的接口,后面看看就明白了。

    3.1 Predicate 实例

    /**
         * Predicate谓词测试,谓词其实就是一个判断的作用类似bool的作用
         */
        @Test
        public void test_Predicate() {
            //① 使用Predicate接口实现方法,只有一个test方法,传入一个参数,返回一个bool值
            Predicate<Integer> predicate = new Predicate<Integer>() {
                @Override
                public boolean test(Integer integer) {
                    if(integer > 5){
                        return true;
                    }
                    return false;
                }
            };
    
            System.out.println(predicate.test(6));
    
            System.out.println("********************");
    
            //② 使用lambda表达式,
            predicate = (t) -> t > 5;
            System.out.println(predicate.test(1));
            System.out.println("********************");
    
        }
    

    输出结果

    3.2 实例分析

    ① Predicate 接口分析

    //① 使用Predicate接口实现方法,只有一个test方法,传入一个参数,返回一个bool值
            Predicate<Integer> predicate = new Predicate<Integer>() {
                @Override
                public boolean test(Integer integer) {
                    if(integer > 5){
                        return true;
                    }
                    return false;
                }
            };
    

    这段代码中,创建了一个 Predicate 接口对象,其中,实现类 test 方法,需要传入一个参数,并且返回一个 bool 值,所以这个接口作用就是判断

    System.out.println(predicate.test(6));
    

    再看,调用 test 方法,传入一个值,就会返回一个 bool 值。

    ② 使用lambda表达式作为 predicate

    //② 使用lambda表达式,
            predicate = (t) -> t > 5;
            System.out.println(predicate.test(1));
            System.out.println("********************");
    

    lambda 表达式返回一个 Predicate 接口,然后调用 test 方法!

    3.3 Predicate 接口实例2

    /**
         * Predicate谓词测试,Predicate作为接口使用
         */
        @Test
        public void test_Predicate2() {
            //① 将Predicate作为filter接口,Predicate起到一个判断的作用
            Predicate<Integer> predicate = new Predicate<Integer>() {
                @Override
                public boolean test(Integer integer) {
                    if(integer > 5){
                        return true;
                    }
                    return false;
                }
            };
    
            Stream<Integer> stream = Stream.of(1, 23, 3, 4, 5, 56, 6, 6);
            List<Integer> list = stream.filter(predicate).collect(Collectors.toList());
            list.forEach(System.out::println);
    
            System.out.println("********************");
    
        }
    

    输出结果

    这段代码,首先创建一个 Predicate 对象,然后实现 test 方法,在 test 方法中做一个判断:如果传入的参数大于 5 ,就返回 true,否则返回 false

    Stream<Integer> stream = Stream.of(1, 23, 3, 4, 5, 56, 6, 6);
            List<Integer> list = stream.filter(predicate).collect(Collectors.toList());
            list.forEach(System.out::println);
    

    这段代码调用 Streamfilter 方法,filter 方法需要的参数就是 Predicate 接口,所以在这里只要大于 5 的数据就会输出。

    3.4 Predicate 接口总结

    ① Predicate 是一个谓词型接口,其实只是起到一个判断作用。
    ② Predicate 通过实现一个 test 方法做判断。

    4 Function 接口

    Function 接口是一个功能型接口,它的一个作用就是转换作用,将输入数据转换成另一种形式的输出数据。

    4.1 Function 接口实例

    /**
         * Function测试,function的作用是转换,将一个值转为另外一个值
         */
        @Test
        public void test_Function() {
            //① 使用map方法,泛型的第一个参数是转换前的类型,第二个是转化后的类型
            Function<String, Integer> function = new Function<String, Integer>() {
                @Override
                public Integer apply(String s) {
                    return s.length();//获取每个字符串的长度,并且返回
                }
            };
    
            Stream<String> stream = Stream.of("aaa", "bbbbb", "ccccccv");
            Stream<Integer> stream1 = stream.map(function);
            stream1.forEach(System.out::println);
    
            System.out.println("********************");
    
        }
    

    输出结果

    4.2 代码分析

    ① Function 接口分析

    //① 使用map方法,泛型的第一个参数是转换前的类型,第二个是转化后的类型
            Function<String, Integer> function = new Function<String, Integer>() {
                @Override
                public Integer apply(String s) {
                    return s.length();//获取每个字符串的长度,并且返回
                }
            };
    

    这段代码创建了一个 Function 接口对象,实现了一个 apply 方法,这个方法有一个输入参数和一个输出参数。其中,泛型的第一个参数是转换前的类型,第二个是转化后的类型。

    在上面的代码中,就是获取字符串的长度,然后将每个字符串的长度作为返回值返回。

    ② 重要应用 map 方法

     Stream<String> stream = Stream.of("aaa", "bbbbb", "ccccccv");
            Stream<Integer> stream1 = stream.map(function);
            stream1.forEach(System.out::println);
    
    

    Function 接口的重要应用不得不说 Stream 类的 map 方法了,map 方法传入一个 Function 接口,返回一个转换后的 Stream类。

    4.3 其他 Function 接口

    除了上面使用的 Function 接口,还可以使用下面这些 Function 接口。
    IntFunction 、DoubleFunction 、LongFunction 、ToIntFunction 、ToDoubleFunction 、DoubleToIntFunction 等等,使用方法和上面一样。

    4.4 Function 接口总结

    ① Function 接口是一个功能型接口,是一个转换数据的作用。
    ② Function 接口实现 apply 方法来做转换。

    5 总结

    通过前面的介绍,已经对Consumer、Supplier、Predicate、Function这几个接口有详细的了解了,其实,这几个接口并不是很难,只是有点抽象,多加理解会发现很简单,并且特别好用!

    展开全文
  • Supplier接口 java.util.function.Supplier<T> 接口仅包含一个无参的方法: T get() 。用来获取一个泛型参数指定类型的对象数据。由于这是一个函数式接口,这也就意味着对应的Lambda表达式需要“对外提供”一...

    JDK提供了大量常用的函数式接口以丰富Lambda的典型使用场景,它们主要在java.util.function 包中被提供。下面是最简单的几个接口及使用示例。

    Supplier接口

    java.util.function.Supplier<T> 接口仅包含一个无参的方法: T get() 。用来获取一个泛型参数指定类型的对象数据。由于这是一个函数式接口,这也就意味着对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据。

    源码:

    
    package java.util.function;
    
    /**
     * Represents a supplier of results.
     *
     * <p>There is no requirement that a new or distinct result be returned each
     * time the supplier is invoked.
     *
     * <p>This is a <a href="package-summary.html">functional interface</a>
     * whose functional method is {@link #get()}.
     *
     * @param <T> the type of results supplied by this supplier
     *
     * @since 1.8
     */
    @FunctionalInterface
    public interface Supplier<T> {
    
        /**
         * Gets a result.
         *
         * @return a result
         */
        T get();
    }
    

    实例:

    实战:求数组元素最大值

     

    Consumer接口

     

    java.util.function.Consumer<T> 接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据,其数据类型由泛型决定。

    package java.util.function;
    
    import java.util.Objects;
    
    /**
     * Represents an operation that accepts a single input argument and returns no
     * result. Unlike most other functional interfaces, {@code Consumer} is expected
     * to operate via side-effects.
     *
     * <p>This is a <a href="package-summary.html">functional interface</a>
     * whose functional method is {@link #accept(Object)}.
     *
     * @param <T> the type of the input to the operation
     *
     * @since 1.8
     */
    @FunctionalInterface
    public interface Consumer<T> {
    
        /**
         * Performs this operation on the given argument.
         *
         * @param t the input argument
         */
        void accept(T t);
    
        /**
         * Returns a composed {@code Consumer} that performs, in sequence, this
         * operation followed by the {@code after} operation. If performing either
         * operation throws an exception, it is relayed to the caller of the
         * composed operation.  If performing this operation throws an exception,
         * the {@code after} operation will not be performed.
         *
         * @param after the operation to perform after this operation
         * @return a composed {@code Consumer} that performs in sequence this
         * operation followed by the {@code after} operation
         * @throws NullPointerException if {@code after} is null
         */
        default Consumer<T> andThen(Consumer<? super T> after) {
            Objects.requireNonNull(after);
            return (T t) -> { accept(t); after.accept(t); };
        }
    }

    抽象方法:accept运行测试:

     

    默认方法:andThen ,如果一个方法的参数和返回值全都是Consumer 类型,那么就可以实现效果:消费数据的时候,首先做一个操作,然后再做一个操作,实现组合。而这个方法就是Consumer 接口中的default方法andThen

    列子:格式化打印信息

     下面的字符串数组当中存有多条信息,请按照格式“ 姓名:XX。性别:XX。”的格式将信息打印出来。要求将打印姓名的动作作为第一个Consumer 接口的Lambda实例,将打印性别的动作作为第二个Consumer 接口的Lambda实例,将两个Consumer 接口按照顺序“拼接”到一起。

    Predicate接口

    有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。这时可以使用java.util.function.Predicate<T> 接口。

    源码查看:

    package java.util.function;
    
    import java.util.Objects;
    
    /**
     * Represents a predicate (boolean-valued function) of one argument.
     *
     * <p>This is a <a href="package-summary.html">functional interface</a>
     * whose functional method is {@link #test(Object)}.
     *
     * @param <T> the type of the input to the predicate
     *
     * @since 1.8
     */
    @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);
    
        /**
         * Returns a composed predicate that represents a short-circuiting logical
         * AND of this predicate and another.  When evaluating the composed
         * predicate, if this predicate is {@code false}, then the {@code other}
         * predicate is not evaluated.
         *
         * <p>Any exceptions thrown during evaluation of either predicate are relayed
         * to the caller; if evaluation of this predicate throws an exception, the
         * {@code other} predicate will not be evaluated.
         *
         * @param other a predicate that will be logically-ANDed with this
         *              predicate
         * @return a composed predicate that represents the short-circuiting logical
         * AND of this predicate and the {@code other} predicate
         * @throws NullPointerException if other is null
         */
        default Predicate<T> and(Predicate<? super T> other) {
            Objects.requireNonNull(other);
            return (t) -> test(t) && other.test(t);
        }
    
        /**
         * Returns a predicate that represents the logical negation of this
         * predicate.
         *
         * @return a predicate that represents the logical negation of this
         * predicate
         */
        default Predicate<T> negate() {
            return (t) -> !test(t);
        }
    
        /**
         * Returns a composed predicate that represents a short-circuiting logical
         * OR of this predicate and another.  When evaluating the composed
         * predicate, if this predicate is {@code true}, then the {@code other}
         * predicate is not evaluated.
         *
         * <p>Any exceptions thrown during evaluation of either predicate are relayed
         * to the caller; if evaluation of this predicate throws an exception, the
         * {@code other} predicate will not be evaluated.
         *
         * @param other a predicate that will be logically-ORed with this
         *              predicate
         * @return a composed predicate that represents the short-circuiting logical
         * OR of this predicate and the {@code other} predicate
         * @throws NullPointerException if other is null
         */
        default Predicate<T> or(Predicate<? super T> other) {
            Objects.requireNonNull(other);
            return (t) -> test(t) || other.test(t);
        }
    
        /**
         * Returns a predicate that tests if two arguments are equal according
         * to {@link Objects#equals(Object, Object)}.
         *
         * @param <T> the type of arguments to the predicate
         * @param targetRef the object reference with which to compare for equality,
         *               which may be {@code null}
         * @return a predicate that tests if two arguments are equal according
         * to {@link Objects#equals(Object, Object)}
         */
        static <T> Predicate<T> isEqual(Object targetRef) {
            return (null == targetRef)
                    ? Objects::isNull
                    : object -> targetRef.equals(object);
        }
    }

    抽象方法:test  。。。Predicate 接口中包含一个抽象方法: boolean test(T t) 。用于条件判断的场景:

    默认方法:and

    默认方法:or  与and 的“与”类似,默认方法or 实现逻辑关系中的“或“

     

    默认方法:negate。。。。“与”、“或”已经了解了,剩下的“非”(取反)也会很简单。。参考文章上面的源码

    或者:

     /**
         * Returns a predicate that represents the logical negation of this
         * predicate.
         *
         * @return a predicate that represents the logical negation of this
         * predicate
         */
        default Predicate<T> negate() {
            return (t) -> !test(t);
        }

    列子

    最后来一个练习:集合信息筛选

    数组当中有多条“姓名+性别”的信息如下,请通过Predicate 接口的拼装将符合要求的字符串筛选到集合ArrayList 中,需要同时满足两个条件:
    1. 必须为女生;
    2. 姓名为4个字。

     

    Function接口

    java.util.function.Function<T,R> 接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。

    源码:

    package java.util.function;
    
    import java.util.Objects;
    
    /**
     * Represents a function that accepts one argument and produces a result.
     *
     * <p>This is a <a href="package-summary.html">functional interface</a>
     * whose functional method is {@link #apply(Object)}.
     *
     * @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);
    
        /**
         * Returns a composed function that first applies the {@code before}
         * function to its input, and then applies this function to the result.
         * If evaluation of either function throws an exception, it is relayed to
         * the caller of the composed function.
         *
         * @param <V> the type of input to the {@code before} function, and to the
         *           composed function
         * @param before the function to apply before this function is applied
         * @return a composed function that first applies the {@code before}
         * function and then applies this function
         * @throws NullPointerException if before is null
         *
         * @see #andThen(Function)
         */
        default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
            Objects.requireNonNull(before);
            return (V v) -> apply(before.apply(v));
        }
    
        /**
         * Returns a composed function that first applies this function to
         * its input, and then applies the {@code after} function to the result.
         * If evaluation of either function throws an exception, it is relayed to
         * the caller of the composed function.
         *
         * @param <V> the type of output of the {@code after} function, and of the
         *           composed function
         * @param after the function to apply after this function is applied
         * @return a composed function that first applies this function and then
         * applies the {@code after} function
         * @throws NullPointerException if after is null
         *
         * @see #compose(Function)
         */
        default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
            Objects.requireNonNull(after);
            return (T t) -> after.apply(apply(t));
        }
    
        /**
         * Returns a function that always returns its input argument.
         *
         * @param <T> the type of the input and output objects to the function
         * @return a function that always returns its input argument
         */
        static <T> Function<T, T> identity() {
            return t -> t;
        }
    }
    

    抽象方法:apply。。。。Function 接口中最主要的抽象方法为: R apply(T t) ,根据类型T的参数获取类型R的结果。使用的场景例如:将String 类型转换为Integer 类型。

    默认方法:andThen。。。。Function 接口中有一个默认的andThen 方法,用来进行组合操作。该方法同样用于“先做什么,再做什么”的场景,和Consumer 中的andThen 差不多:

    第一个操作是将字符串解析成为int数字,第二个操作是乘以10。两个操作通过andThen 按照前后顺序组合到了一起。

    实例;自定义函数模型拼接

    String str = "赵丽颖,20";

    1. 将字符串截取数字年龄部分,得到字符串;
    2. 将上一步的字符串转换成为int类型的数字;
    3. 将上一步的int数字累加100,得到结果int数字。

    基本上理解的就这些了。。代码地址:https://github.com/itwsj/Java8demo

     

    展开全文
  • Supplier接口

    2021-02-18 14:52:22
    1、 Supplier接口 该接口仅包含一个无参的方法: T get() 。用来获取一个泛型参数指定类型的对象数据。 Supplier接口被称之为生产型接口,指定接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据 /* ...

    1、 Supplier接口

    该接口仅包含一个无参的方法: T get() 。用来获取一个泛型参数指定类型的对象数据。

    Supplier接口被称之为生产型接口,指定接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据

    /*
    * 接口仅包含一个无参的方法: T get() 。用来获取一个泛型参数指定类型的对象数据。
    *
    * Supplier<T>接口被称之为生产型接口,指定接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据
    * */
    public class Demo01Supplier {
        //定义一个方法,方法的参数传递Supplier<T>接口,泛型执行String,get方法就会返回一个String
        public static String getString(Supplier<String> supplier){
            return supplier.get();
        }
    
        public static void main(String[] args) {
            //调用getString方法,方法的参数Supplier是一个函数式接口,所以可以传递Lambda表达式
            String s = getString(() -> "胡歌");
            System.out.println(s);
        }
    }
    

    练习:求数组元素最大值

    使用 Supplier 接口作为方法参数类型,通过Lambda表达式求出int数组中的最大值。提示:接口的泛型请使用 java.lang.Integer 类。

    public class Demo02Supplier {
        //定义一个方法,方法的参数传递Supplier,泛型使用Integer
        public static int getMax(Supplier<Integer> supplier){
            return supplier.get();
        }
    
        public static void main(String[] args) {
            int arr[] = {2,3,4,52,333,23};
    
            //调用getMax方法,参数传递Lambda
            int v = getMax(()->{
               int max = 0;
               //计算数组的最大值
               for (int i = 0; i < arr.length; i++) {
                   if (max < arr[i]){
                       max = arr[i];
                   }
                }
               return max;
            });
            System.out.println(v);
        }
    }
    
    展开全文
  • JDK8 | Supplier实践应用

    2020-08-28 11:43:06
    场景再现2.Supplier3.总结 最近呢,看到应该系统应用中有一个一二级缓存模块的设计,早期设计虽然鉴于当时实践考虑已经自我感觉涉及还不错,但是最近再看到这块代码,有一种想要继续提炼升华的冲动。鉴于此,有了本...

    最近呢,看到应该系统应用中有一个一二级缓存模块的设计(基于google guava和redis的一二级缓存设计实现),早期设计虽然鉴于当时实践考虑已经自我感觉涉及还不错,但是最近再看到这块代码,有一种想要继续提炼升华的冲动。鉴于此,有了本篇中在设计中基于Supplier的实践场景应用。

    1.场景再现

    类图

    如上图,抽象类AbstractCacheManager<K,HK,V>的若干个子类实现了相关方法,但是部分方法依然存在冗余特征。

    我们来看一下子类的实现示例

    /**
     * @description: 行政编码-缓存管理器
     * @Date : 2019/5/5 下午5:32
     * @Author : 石冬冬-Seig Heil
     */
    @Component
    @Slf4j
    public class SimpleDistrictCacheManager extends AbstractCacheManager<String,String,Result<List<SimpleDistrictRe>>> {
    
        @Autowired
        DiamondConfig diamondConfig;
    
        @Autowired
        DictionaryRegFacade dictionaryRegFacade;
        /**
         * short name
         */
        final String SHORT_NAME = CacheShortName.simpleDistrictCache.name();
        /**
         * 省份列表缓存key
         */
        final String PROVINCE_CACHE_KEY = "provinceCache";
        /**
         * 二级行政缓存key
         */
        final String SECONDARY_DISTRICT_CACHE_KEY = "secondaryDistrictCache";
        /**
         * 行政缓存key
         */
        final String DISTRICT_CACHE_KEY = "districtCache";
        /**
         * 联动缓存 Key 前缀
         */
        final String GANGED_CACHE_KEY = "gangedCache";
        /**
         * 默认失效时间-2小时(单位秒)
         */
        final long DEFAULT_EXPIRE_SECONDS = 7200;
        /**
         * 根据父级行政查询下级
         * @param parentCode
         * @return
         */
        public Result<List<SimpleDistrictRe>> queryCitiesByParentCode(String parentCode){
            if(!useCache()){
                return dictionaryRegFacade.queryCitiesByParentCode(parentCode);
            }
            Result<List<SimpleDistrictRe>> queryResult;
            try {
                CacheContext<Result<List<SimpleDistrictRe>>> context = CacheContext.<Result<List<SimpleDistrictRe>>>builder()
                        .key(parentCode).reference(TypeReferences.SIMPLE_DISTRICT_TYPE).expireSeconds(DEFAULT_EXPIRE_SECONDS)
                        .callback(() -> Optional.ofNullable(dictionaryRegFacade.queryCitiesByParentCode(parentCode))).build();
                queryResult = primaryCache().get(parentCode,() -> super.getFromSecondary(context));
            } catch (ExecutionException e) {
                log.info("{} focus on an exception,then execute queryDB,parentCode={}",SHORT_NAME,parentCode,e);
                queryResult = dictionaryRegFacade.queryCitiesByParentCode(parentCode);
                log.info("{} focus on an exception,then execute queryDB,parentCode={},value={}",SHORT_NAME,parentCode, JSONObject.toJSONString(queryResult));
            }
            return queryResult;
        }
    
        /**
         * 查询省份列表
         * @return
         */
        public Result<List<SimpleDistrictRe>> queryProvinces(){
            if(!useCache()){
                return dictionaryRegFacade.queryProvinces();
            }
            Result<List<SimpleDistrictRe>> queryResult;
            try {
                CacheContext<Result<List<SimpleDistrictRe>>> context = CacheContext.<Result<List<SimpleDistrictRe>>>builder()
                        .key(PROVINCE_CACHE_KEY).reference(TypeReferences.SIMPLE_DISTRICT_TYPE).expireSeconds(DEFAULT_EXPIRE_SECONDS)
                        .callback(() -> Optional.ofNullable(dictionaryRegFacade.queryProvinces())).build();
                queryResult = primaryCache().get(PROVINCE_CACHE_KEY,() -> super.getFromSecondary(context));
            } catch (ExecutionException e) {
                log.info("{} focus on an exception,then execute queryDB",SHORT_NAME,e);
                queryResult = dictionaryRegFacade.queryProvinces();
                log.info("{} focus on an exception,then execute value={}",SHORT_NAME,JSONObject.toJSONString(queryResult));
            }
            return queryResult;
        }
    
        /**
         * 查询二级城市
         * @return
         */
        public Result<List<SimpleDistrictRe>> querySecondaryDistricts(){
            if(!useCache()){
                return dictionaryRegFacade.querySecondaryDistricts();
            }
            Result<List<SimpleDistrictRe>> queryResult;
            try {
                CacheContext<Result<List<SimpleDistrictRe>>> context = CacheContext.<Result<List<SimpleDistrictRe>>>builder()
                        .key(SECONDARY_DISTRICT_CACHE_KEY).reference(TypeReferences.SIMPLE_DISTRICT_TYPE).expireSeconds(DEFAULT_EXPIRE_SECONDS)
                        .callback(() -> Optional.ofNullable(dictionaryRegFacade.querySecondaryDistricts())).build();
                queryResult = primaryCache().get(SECONDARY_DISTRICT_CACHE_KEY,() -> super.getFromSecondary(context));
            } catch (ExecutionException e) {
                log.info("{} focus on an exception,then execute queryDB",SHORT_NAME,e);
                queryResult = dictionaryRegFacade.queryProvinces();
                log.info("{} focus on an exception,then execute value={}",SHORT_NAME,JSONObject.toJSONString(queryResult));
            }
            return queryResult;
        }
    
        /**
         * 查询所有行政列表
         * @return
         */
        public Result<List<SimpleDistrictRe>> queryAll(){
            if(!useCache()){
                return dictionaryRegFacade.queryAll();
            }
            Result<List<SimpleDistrictRe>> queryResult;
            try {
                CacheContext<Result<List<SimpleDistrictRe>>> context = CacheContext.<Result<List<SimpleDistrictRe>>>builder()
                        .key(DISTRICT_CACHE_KEY).reference(TypeReferences.SIMPLE_DISTRICT_TYPE).expireSeconds(DEFAULT_EXPIRE_SECONDS)
                        .callback(() -> Optional.ofNullable(dictionaryRegFacade.queryAll())).build();
                queryResult = primaryCache().get(DISTRICT_CACHE_KEY,() -> super.getFromSecondary(context));
            } catch (ExecutionException e) {
                log.info("{} focus on an exception,then execute queryDB",SHORT_NAME,e);
                queryResult = dictionaryRegFacade.queryAll();
                log.info("{} focus on an exception,then execute value={}",SHORT_NAME,JSONObject.toJSONString(queryResult));
            }
            return queryResult;
        }
    
        /**
         * 联动查询行政列表
         * @param dto
         * @return
         */
        public Result<List<SimpleDistrictRe>> queryWithGanged(DistrictGangedDTO dto) {
            if(!useCache()){
                return dictionaryRegFacade.queryWithGanged(dto);
            }
            Result<List<SimpleDistrictRe>> queryResult;
            StringBuilder keyBuilder = new StringBuilder(GANGED_CACHE_KEY).append(":").append(dto.getRegLevel());
            if(StringTools.isNotEmpty(dto.getGbCode())) {
                keyBuilder.append(":").append(dto.getGbCode());
            }
            try {
                CacheContext<Result<List<SimpleDistrictRe>>> context = CacheContext.<Result<List<SimpleDistrictRe>>>builder()
                        .key(keyBuilder.toString()).reference(TypeReferences.SIMPLE_DISTRICT_TYPE).expireSeconds(DEFAULT_EXPIRE_SECONDS)
                        .callback(() -> Optional.ofNullable(dictionaryRegFacade.queryWithGanged(dto))).build();
                queryResult = primaryCache().get(keyBuilder.toString(),() -> super.getFromSecondary(context));
            } catch (ExecutionException e) {
                log.info("{} focus on an exception,then execute queryDB",SHORT_NAME,e);
                queryResult = dictionaryRegFacade.queryWithGanged(dto);
                log.info("{} focus on an exception,then execute value={}",SHORT_NAME,JSONObject.toJSONString(queryResult));
            }
            return queryResult;
        }
    
        @Override
        public Cache<String, Result<List<SimpleDistrictRe>>> primaryCache() {
            return SimpleDistrictCacheFactory.get();
        }
    
        @Override
        public boolean useCache() {
            boolean useCache = false;
            try {
                useCache = cacheSwitch().simpleDistrictEnable;
                log.info("{} useCache={}",SHORT_NAME,useCache);
            } catch (Exception e) {
                log.error("{} useCache={}",SHORT_NAME,useCache,e);
            }
            return useCache;
        }
    
        @Override
        public String shortName() {
            return SHORT_NAME;
        }
    
    }
    

    如上述子类SimpleDistrictCacheManager,在实现抽象类相关方法时,并对外部提供的相关方法,譬如Result<List<SimpleDistrictRe>> queryCitiesByParentCode(String parentCode)Result<List<SimpleDistrictRe>> queryProvinces()
    我们仔细发现都存在相同的业务动作。

    • 判断是否开启缓存,关闭时从数据库加载。
    • 构建上下文对象CacheContext,然后调用primaryCache().get(x,() -> super.getFromSecondary(context))方法。
    • 而且都通过try…catch…包裹。

    分析上述业务动作,这就是明显的模板方法,鉴于此,我们把每个子类共同冗余的模板动作提取到抽象类AbstractCacheManager中。

    提取一个公共方法V fromCache(K key,CacheContext<V> context,Supplier<V> dataSourceCaller)如下:

    /**
     * 从缓存中获取数据
     * 执行逻辑:
     * (1)、缓存开关关闭时,从 dataSourceCaller 获取。
     * (2)、缓存开关开启时,从一级缓存获取,一级缓存没有则从二级缓存获取。
     * @param key 缓存Key
     * @param context 构建缓存上下文对象
     * @param dataSourceCaller 数据库查找回调器
     * @return
     */
    V fromCache(K key,CacheContext<V> context,Supplier<V> dataSourceCaller){
        final String SHORT_NAME = shortName();
        if(!useCache()){
            return dataSourceCaller.get();
        }
        V queryResult;
        try {
            queryResult = primaryCache().get(key,() -> getFromSecondary(context));
        } catch (ExecutionException e) {
            log.info("[{}]ExecutionException,degraded queryDB",SHORT_NAME,e);
            queryResult = dataSourceCaller.get();
            log.info("[{}]ExecutionException,degraded queryDB={}",SHORT_NAME,JSONObject.toJSONString(queryResult));
        }
        return queryResult;
    }
    

    上述,既然抽象类AbstractCacheManager<K,HK,V>定义为泛型,其中K为缓存key,HK为缓存小Key,V作为缓存加载的返回值。所以我们根据规约,封装
    如上方法,我们使用了一个jdk8中的一个函数,Supplier<T>,该函数通过获取可以拿到我们指定类型的返回值<V>

    修改SimpleDistrictCacheManager的方法实现

    @Component
    @Slf4j
    public class SimpleDistrictCacheManager extends AbstractCacheManager<String,String,Result<List<SimpleDistrictRe>>> {
    
        @Autowired
        DictionaryRegFacade dictionaryRegFacade;
        /**
         * short name
         */
        static final String SHORT_NAME = CacheShortName.simpleDistrictCache.name();
        /**
         * 省份列表缓存key
         */
        static final String PROVINCE_CACHE_KEY = "provinceCache";
        /**
         * 二级行政缓存key
         */
        static final String SECONDARY_DISTRICT_CACHE_KEY = "secondaryDistrictCache";
        /**
         * 行政缓存key
         */
        static final String DISTRICT_CACHE_KEY = "districtCache";
        /**
         * 联动缓存 Key 前缀
         * {0} 行政级别
         * {1} 国标码
         */
        static final String GANGED_CACHE_KEY_PATTERN = "gangedCache:{0}:{1}";
        /**
         * 默认失效时间-2小时(单位秒)
         */
        static final long DEFAULT_EXPIRE_SECONDS = 7200;
        /**
         * 根据父级行政查询下级
         * @param parentCode
         * @return
         */
        public Result<List<SimpleDistrictRe>> queryCitiesByParentCode(String parentCode){
            return fromCache(parentCode,
                    buildContext(parentCode,() -> Optional.ofNullable(dictionaryRegFacade.queryCitiesByParentCode(parentCode))),
                    () -> dictionaryRegFacade.queryCitiesByParentCode(parentCode));
        }
    
        /**
         * 查询省份列表
         * @return
         */
        public Result<List<SimpleDistrictRe>> queryProvinces(){
            return fromCache(PROVINCE_CACHE_KEY,
                    buildContext(PROVINCE_CACHE_KEY,() -> Optional.ofNullable(dictionaryRegFacade.queryProvinces())),
                    () -> dictionaryRegFacade.queryProvinces());
        }
    
        /**
         * 查询二级城市
         * @return
         */
        public Result<List<SimpleDistrictRe>> querySecondaryDistricts(){
            return fromCache(SECONDARY_DISTRICT_CACHE_KEY,
                    buildContext(SECONDARY_DISTRICT_CACHE_KEY,() -> Optional.ofNullable(dictionaryRegFacade.querySecondaryDistricts())),
                    () -> dictionaryRegFacade.querySecondaryDistricts());
        }
    
        /**
         * 查询所有行政列表
         * @return
         */
        public Result<List<SimpleDistrictRe>> queryAll(){
            return fromCache(DISTRICT_CACHE_KEY,
                    buildContext(DISTRICT_CACHE_KEY,() -> Optional.ofNullable(dictionaryRegFacade.queryAll())),
                    () -> dictionaryRegFacade.queryAll());
        }
    
        /**
         * 联动查询行政列表
         * @param dto
         * @return
         */
        public Result<List<SimpleDistrictRe>> queryWithGanged(DistrictGangedDTO dto) {
            String cacheKey = MessageFormat.format(GANGED_CACHE_KEY_PATTERN,dto.getRegLevel(),dto.getGbCode());
            return fromCache(cacheKey,
                    buildContext(cacheKey,() -> Optional.ofNullable(dictionaryRegFacade.queryWithGanged(dto))),
                    () -> dictionaryRegFacade.queryWithGanged(dto));
        }
    
        /**
         * 构建缓存上下文对象
         * @param cacheKey 缓存key
         * @param supplier 数据库接口查询回调
         * @return
         */
        CacheContext<Result<List<SimpleDistrictRe>>> buildContext(String cacheKey,Supplier<Optional<Result<List<SimpleDistrictRe>>>> supplier){
            return  CacheContext.<Result<List<SimpleDistrictRe>>>builder()
                    .key(cacheKey).reference(TypeReferences.SIMPLE_DISTRICT_TYPE).expireSeconds(DEFAULT_EXPIRE_SECONDS)
                    .callback(supplier).build();
        }
    
        @Override
        public Cache<String, Result<List<SimpleDistrictRe>>> primaryCache() {
            return SimpleDistrictCacheFactory.get();
        }
    
        @Override
        public boolean useCache() {
            boolean useCache = false;
            try {
                useCache = cacheSwitch().simpleDistrictEnable;
                log.debug("{} useCache={}",SHORT_NAME,useCache);
            } catch (Exception e) {
                log.error("{} useCache={}",SHORT_NAME,useCache,e);
            }
            return useCache;
        }
    
        @Override
        public String shortName() {
            return SHORT_NAME;
        }
    
    }
    

    只需要调用抽象类的 fromCache方法即可,同时在类,进而把CacheContext的对象实例构建提取了一个方法。就是如下:
    但是总体上发现这些对外提供的方法清爽简洁了许多(try…catch不见了诶等等)。

    /**
     * 构建缓存上下文对象
     * @param cacheKey 缓存key
     * @param supplier 数据库接口查询回调
     * @return
     */
    CacheContext<Result<List<SimpleDistrictRe>>> buildContext(String cacheKey,Supplier<Optional<Result<List<SimpleDistrictRe>>>> supplier){
        return  CacheContext.<Result<List<SimpleDistrictRe>>>builder()
                .key(cacheKey).reference(TypeReferences.SIMPLE_DISTRICT_TYPE).expireSeconds(DEFAULT_EXPIRE_SECONDS)
                .callback(supplier).build();
    }
    

    2.Supplier

    @FunctionalInterface
    public interface Supplier<T> {
    
        /**
         * Gets a result.
         *
         * @return a result
         */
        T get();
    }
    

    该函数可以返回指定类型,通过标注@FunctionalInterface,声明该方法支持lambda表达式。
    在JDK8之前,我们通过需要new Supplier并实现get()方法,这也就是所谓内部匿名类的实现方式。
    而JDK8 lambda就是简化这一冗余的代码,只需要 () -> xx一个代码语义表达即可。

    3.总结

    其实,JDK,stream api大量通过BiFunctionBiConsumerFunctionPredicateConsummerSupplier函数实现函数式编程,而仔细
    查看他们源码,发现都通过@FunctionalInterface标注一个注解,以支持lambda表达式。

    下面的是我的公众号二维码图片,欢迎关注。
    我的公众号二维码

    展开全文
  • Supplier_Guide_for_Product_Development-2018
  • Java Supplier是一个功能接口,代表结果的提供者。 Supplier的功能方法是get()。 一个Supplier可以通过lambda表达式、方法引用或默认构造函数来实例化。 Supplier在Java 8中被引入,属于java.util.function包。 ...
  • 供应商选择是供应链管理背景下的一项重要战略决策。关于供应商选择问题的现有文献侧重于评估主要(例如,成本、质量、交货期)和绿色(例如,CO2排放、环境做法)标准。然而,由于竞争性和全球供应链的出现(以及它们所...
  • 下载Snags Supplier GitHub Repo 使用协议 通过使用此源代码,您同意: 制作自己的项目 不是Snags供应商的精确克隆(不同的用法/构想) 将您的BOT /项目发布到网站时,必须包含指向我们的源代码或信用的链接 额外...
  • 文章目录一、Supplier是什么?二、lambda表达式的Supplier使用三、方法引用的supplier使用 一、Supplier是什么? 函数式接口(一个接口,只含有一个抽象方法) 属于java.util.function包 与之对应的consumer接受一个...
  • 这是表中的数据: Weather.xml: ... select area_name from weather_table where cur_weather is null and province_name=#{provinceName} ... select id from weather... Supplier<List<T>> supplier1, Comparator...
  • JDK1.8 Supplier实践及总结

    千次阅读 2019-11-09 15:18:24
    正好之前笔者在Supplier上有一些实践,因此打算跟大家分享一下使用经验 基础知识 JDK1.8为我们提供了一个函数接口Supplier,先来看一下它的接口定义 @FunctionalInterface public interface Supplier<T> { /...
  • 【JAVA8】快速理解Consumer、Supplier、Predicate与Function

    千次阅读 多人点赞 2019-11-07 09:56:34
    快速理解Consumer、Supplier、Predicate与Function 一、前言 这几个接口都处在java.util.function包下,Consumer(消费型),Supplier(供给型)、Predicate(判断型)与Function(转换型),暂时不理解他们的类型...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 44,473
精华内容 17,789
关键字:

supplier