zoukankan      html  css  js  c++  java
  • jdk8函数接口

    java8 新特性推出的 Lambda 表达式,即函数式编程,相信很多开发胸弟都会使用了,但是什么是函数式编程呢?别问我,我也不知道标准的定义。其核心思想是:使用不可变值和函数,函数对一个值进行处理,映射成另一个值

    函数接口

    java8之前接口类只有方法的定义,没有实现的,Java8对接口提供默认方法的新特性。一个接口类可以定义n个抽象方法,但如果有 @FunctionalInterface 注解修饰就不一样了,该注释会强制编译检查一个接口是否符合函数接口的标准。如果该注释添加给一个枚举类型、类或另一个注释,或者接口包含不止一个抽象方法,编译就会报错。@FunctionalInterface 注解修饰的接口就是被定义成函数接口。

    常用的函数接口

    平时开发中常用的函数接口有无返回值的Consumer,返回值为Boolean的Predicate,把入参T映射成R返回值的Function 和返回实例对象的Supplier。接下来我们一起分析这四个函数接口类的源码以及简单的使用,先创建一个后面需要用到的实体类 Griez。

    public class Griez implements Serializable {
        private int age;
        private String name;
        public Griez(int age, String name) {
            this.age = age;
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public Griez setAge(int age) {
            this.age = age;
            return this;
        }
    
        public String getName() {
            return name;
        }
    
        public Griez setName(String name) {
            this.name = name;
            return this;
        }
    }
    

    定义一个法国球星格子(我最喜欢的球员)类,为了简单这里只有名字和年龄,他的能力值和薪资就不展示出来了,怕吓到大家。

    Consumer

    @FunctionalInterface
    public interface Consumer<T> {
    		// 执行时需要调用传入的实现
        void accept(T t);
    
        default Consumer<T> andThen(Consumer<? super T> after) {
            Objects.requireNonNull(after);
            return (T t) -> { accept(t); after.accept(t); };
        }
    }
    

    Consumer函数接口有两个方法,抽象方法accept需要调用者自己实现;andThen默认方法封装了两个Consumer执行顺序的Consumer实例,先执行本实例的accept,再执行参数after的accept方法。

        public static void main(String[] args) {
            Consumer<Griez> consumer = griez -> System.out.println(griez.getName() + griez.age);
            Consumer<Griez> afterConsumer = griez -> System.out.println(griez.getAge());
            Consumer<Griez> then = consumer.andThen(afterConsumer);
            then.accept(new Griez(29, "wolf"));
        }
    

    第1,2行创建Consumer实例,并实现了accept方法。记得刚毕业出来面试有个面试官问我接口能不能创建实例,我给他的回答是:“你说呢?”。

    Predicate

    @FunctionalInterface
    public interface Predicate<T> {
    
        boolean test(T t);
    		// 两个条件必须满足
        default Predicate<T> and(Predicate<? super T> other) {
            Objects.requireNonNull(other);
            return (t) -> test(t) && other.test(t);
        }
        // 传说中的 逻辑非 判断
        default Predicate<T> negate() {
            return (t) -> !test(t);
        }
        // 逻辑或判断
        default Predicate<T> or(Predicate<? super T> other) {
            Objects.requireNonNull(other);
            return (t) -> test(t) || other.test(t);
        }
        // 对象判断?
        static <T> Predicate<T> isEqual(Object targetRef) {
            return (null == targetRef)
                    ? Objects::isNull
                    : object -> targetRef.equals(object);
        }
    }
    

    test 方法需要自定义逻辑,返回一个boolean值,该函数接口是做判断用途的。and 方法是两个Predicate 逻辑与判断;negate 方法是逻辑非判断;or 方法是两个 Predicate 逻辑或判断;isEqual 方法是判断targetRef是否与本实例相同。

    public static void main(String[] args) {
        Predicate<Griez> predicate= griez -> griez.getAge() > 18;
        System.out.println("Griez已经成年了 : " + predicate.test(new Griez(29, "griez")));
    }
    

    test返回Boolean值。

    Function

    @FunctionalInterface
    public interface Function<T, R> {
    
        R apply(T t);
    
        default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
            Objects.requireNonNull(before);
            return (V v) -> apply(before.apply(v));
        }
        default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
            Objects.requireNonNull(after);
            return (T t) -> after.apply(apply(t));
        }
        static <T> Function<T, T> identity() {
            return t -> t;
        }
    }
    

    apply 方法接收一个T参数,然后一个R,该方法是类型映射作用。compose 方法是组装了两个Function执行顺序行为Function对象,先执行参数的Function在执行本实例Function。andThen 跟 compose执行顺序相反。identity 方法是返回参数本身。

    public static void main(String[] args) {
        Function function = o -> new Griez(20, "Female");
        System.out.println(function.apply(new Griez(29, "griez").getName()));
    }
    

    一个大老爷进去变成一个年轻小姐姐出来,变态的程序员。

    Supplier

    @FunctionalInterface
    public interface Supplier<T> {
        T get();
    }
    

    该函数接口看上去就比较寒颤了,只有一个方法。get 方法作用如名字一个,伸手党来的,获取一个实例。

    public static void main(String[] args) {
        Supplier<Griez> supplier = () -> new Griez(29, "griez");
        System.out.println(supplier.get());
    }
    

    获取一个Griez对象。

  • 相关阅读:
    vue2.0 keep-alive最佳实践
    Vue解决安卓4.4不兼容的问题
    体验异步的终极解决方案-ES7的Async/Await
    axios在vue中的简单配置与使用
    AngularJS-UI-Router
    SignalR 填坑记
    小心C# 5.0 中的await and async模式造成的死锁
    使用BCP导出导入数据
    关闭正在执行的事务 Kill
    C# 正则表达式
  • 原文地址:https://www.cnblogs.com/wolf-bin/p/12388870.html
Copyright © 2011-2022 走看看