zoukankan      html  css  js  c++  java
  • 常用的函数式接口

    常用函数式接口

    • 仅含有一个抽象方法的接口(不是只有一个方法)
    • 该接口常与Lambda表达式相联系
    • Lambda表达式延迟加载,可避免性能浪费

    Supplier -生产型接口


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

    • Supplier<>接口被称为生产型接口,指定接口的泛型是什么类型,那么接口的get方法就会生产什么类型的数据,有返回值。

    package cn.learn;
    
    import java.util.function.Supplier;
    
    public class function {
        //定义一个方法,方法参数传递Supplier<>接口,泛型执行String.get方法就会返回一个String
        public static String getString(Supplier<String> stringSupplier){
            return stringSupplier.get();
        }
    
        public static void main(String[] args) {
            //调用getString方法,方法的参数是一个函数式表达接口,所以传递lambda表达式
            String str = getString(() ->{
               //生产一个字符串,并返回
               return "aaa"; 
            });
    
            System.out.println(str);
    
            //优化Lambda表达式
            str = getString(() -> "aaa");
    
            System.out.println(str);
            
        }
    }
    
    

    练习:求数组元素最大值


    package cn.learn;
    
    import java.util.function.Supplier;
    
    public class function {
        public static Integer getMax(Supplier<Integer> stringSupplier){
            return stringSupplier.get();
        }
    
        public static void main(String[] args) {
            //定义一个数组
            int[] arr = new int[]{3,55,66,77,88,-5};
    
            //调用getMax方法,使用Lambda表达式简写
            int integermax = getMax(() ->{
               //获取数组最大值并返回
               int max = arr[0];
                for (int i = 1; i < arr.length; i++) {
                    if (max < arr[i]){
                        max = arr[i];
                    }
                }
                return max;
            });
    
            /******
            //调用getMax方法
            getMax(new Supplier<Integer>() {
                @Override
                public Integer get() {
                    //获取数组最大值并返回
                    int max = arr[0];
                    for (int i = 1; i < arr.length; i++) {
                        if (max < arr[i]) {
                            max = arr[i];
                        }
                    }
                    return max;
                }
            });
            *******/
    
            System.out.println(integermax);
        }
    }
    
    

    Consumer -消费型接口


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

    • Consumer接口中包含抽象方法void accept(T t),意为消费一个指定泛型的数据,无返回值

    package cn.learn;
    
    import java.util.function.Consumer;
    
    public class function {
        //accept方法接受的数据可以输出、计算等
        public static void print(Integer year,Consumer<Integer> age){
            age.accept(year);
        }
    
        public static void main(String[] args) {
    
            //消费方式:直接输出
            print(2018,(year) -> System.out.println("你的出生年是"+year));
    
            //消费方式:反转字符串
            print(2018,(year) -> {
                String string = year.toString();
                String re = new StringBuilder(string).reverse().toString();
                System.out.println(re);
            });
        }
    }
    
    
    • Consumer方法中的默认方法——andThen

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

    • JDK源码

       default Consumer<T> andThen(Consumer<? super T> after) {
            Objects.requireNonNull(after);
            return (T t) -> { accept(t); after.accept(t); };
        }
    

    注:java.util.Object的requireNonNull静态方法将会在参数为null时主动抛出NullPointerException异常,这就省去编写if语句和抛出空指针异常的麻烦。

    • 若想实现组合效果,需要两个Lambda表达式即可,而andThen的语义正是“一步接一步”操作,例如两个步骤组合的情况:

      • Consumer<泛型String> con1;
        Consumer<泛型String> con2;
        String str = "hello";
        con1.accept(str);
        con2.accept(str);
    
    package cn.learn;
    
    import java.util.function.Consumer;
    
    public class function {
        //把两个Consumer接口组合到一起,再对数据进行消费
        public static void method(String str,Consumer<String> con1,Consumer<String> con2){
            
            //使用原始方式
            con1.accept(str);
            con2.accept(str);
            
        }
    
        public static void main(String[] args) {
            
            //原始使用方式,调用method方法,需要传递两个Lambda表达式
            method("Hello",(str) -> {
                //消费方式:转为大写
                System.out.println(str.toUpperCase());
            },(str) ->{
                //消费方式:转为小写
                System.out.println(str.toLowerCase());
            });
            
        }
    }
    
    
    • 连接两个接口再进行消费(谁在前,谁先消费),可以改为
      con1.andThen(con2).accept(str);
    package cn.learn;
    
    import java.util.function.Consumer;
    
    public class function {
        //andThen需要两个Consumer接口,可以把两个Consumer接口组合到一起,再对数据进行消费
        public static void method(String str,Consumer<String> con1,Consumer<String> con2){
            
            //先使用con1消费数据,再使用con2
            con1.andThen(con2).accept(str);
    
        }
    
        public static void main(String[] args) {
    
            //原始使用方式,调用method方法,需要传递两个Lambda表达式
            method("Hello",(str) -> {
                //消费方式:转为大写
                System.out.println(str.toUpperCase());
            },(str) ->{
                //消费方式:转为小写
                System.out.println(str.toLowerCase());
            });
    
        }
    }
    
    

    练习:格式化打印信息


    package cn.learn;
    
    import java.util.function.Consumer;
    
    public class function {
        //使用两个Consumer来消费字符串,泛型为字符数组
        public static void method(String[] str,Consumer<String[]> con1,Consumer<String[]> con2){
    
            //先使用con1消费数据,再使用con2
            con1.andThen(con2).accept(str);
    
        }
    
        public static void main(String[] args) {
    
            //定义一个字符串数组
            String[] person ={"小王,男","大王,女"};
    
            //原始使用方式,调用method方法,需要传递两个Lambda表达式
            method(person,(str) -> {
                //消费方式:取人名
                for (String name:str) {
                    //取第一个元素
                    System.out.println(name.split(",")[0]);
                }
            },(str) ->{
                //消费方式:取性别
                for (String name:str) {
                    //取第一个元素
                    System.out.println(name.split(",")[1]);
                }
            });
        }
    }
    
    

    结果:
    小王
    大王

    • 另一种写法

    package cn.learn;
    
    import java.util.function.Consumer;
    
    public class function {
        //使用两个Consumer来消费字符串,泛型为字符数组
        public static void method(String[] str,Consumer<String> con1,Consumer<String> con2){
            //将遍历写在此处,预防重复造轮子
            for (String message:str) {
                //先使用con1消费数据,再使用con2
                con1.andThen(con2).accept(message);
            }
    
    
        }
    
        public static void main(String[] args) {
    
            //定义一个字符串数组
            String[] person ={"小王,男","大王,女"};
    
            //原始使用方式,调用method方法,需要传递两个Lambda表达式
            method(person,(message) -> {
                //消费方式:取人名
                    System.out.println(message.split(",")[0]);
            },(message) ->{
                //消费方式:取性别
                    System.out.println(message.split(",")[1]);
            });
        }
    }
    
    

    结果:
    小王

    大王

    Predicate -判断接口


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

    • Predicate接口中含有一个抽象方法:boolean test(T t)。用于条件判断的场景,返回值为布尔值

    package cn.learn;
    
    import java.util.function.Predicate;
    
    public class function {
        //
        public static boolean checkMethod(String str, Predicate<String> pre){
            return pre.test(str);
        }
    
        public static void main(String[] args) {
    
            String str = "hello"; 
    
            //对字符串进行校验
            boolean check = checkMethod(str,(String str01) ->{
               return str01.length()>5;
            });
    
            boolean check1 = checkMethod(str,str01 -> str01.length()>3);
    
            System.out.println(check);
            System.out.println(check1);
        }
    }
    
    * 默认方法:and -可以判断多个判断条件和“&&”差不多
    
    ```java
    package cn.learn;
    
    import java.util.function.Predicate;
    
    public class function {
        //
        public static boolean checkMethod(String str, Predicate<String> pre1, Predicate<String> pre2){
            //等价于return pre1.test(str) && pre2.test(str);
            return pre1.and(pre2).test(str);
        }
    
        public static void main(String[] args) {
    
            String str = "hello";
    
            //对字符串进行校验
            boolean check = checkMethod(str,(String str01) ->{
               return str01.length()>3;
            },(str01) ->{
                return str01.contains("1");
            });
    
    
            System.out.println(check);
        }
    }
    
    

    false

    • 默认方法:or -可以判断多个判断条件和“||”差不多
    package cn.learn;
    
    import java.util.function.Predicate;
    
    public class function {
        //
        public static boolean checkMethod(String str, Predicate<String> pre1, Predicate<String> pre2){
            //等价于return pre1.test(str) || pre2.test(str);
            return pre1.or(pre2).test(str);
        }
    
        public static void main(String[] args) {
    
            String str = "hello";
    
            //对字符串进行校验
            boolean check = checkMethod(str,(String str01) ->{
               return str01.length()>3;
            },(str01) ->{
                return str01.contains("1");
            });
    
    
            System.out.println(check);
        }
    }
    
    

    true

    • 默认方法:negate -可以判断多个判断条件和“!”差不多
    
    package cn.learn;
    
    import java.util.function.Predicate;
    
    public class function {
        //
        public static boolean checkMethod(String str, Predicate<String> pre1){
            //等价于return !pre1.test(str);
            return pre1.negate().test(str);
        }
    
        public static void main(String[] args) {
    
            String str = "hello";
    
            //对字符串进行校验
            boolean check = checkMethod(str,(String str01) ->{
               return str01.length()>3;
            });
    
    
            System.out.println(check);
        }
    }
    
    

    false

    练习:集合信息筛选


    • 将名字为2个字且为女生的字符串选到集合中,注意字符串判断需要用equals方法
    package cn.learn;
    
    import java.util.ArrayList;
    import java.util.function.Predicate;
    
    public class function {
    
        public static ArrayList<String> filter(String[] str, Predicate<String> pre1, Predicate<String> pre2) {
    
            //放外边,里边会重复申请
            ArrayList<String> correct = new ArrayList<>();
            //遍历数组
            for (String message : str) {
                boolean ifCorr = pre1.and(pre2).test(message);
                //满足条件的放入集合
                if (ifCorr) {
                    correct.add(message);
                }
            }
            return correct;
    
        }
    
        public static void main(String[] args) {
    
            String[] str = {"小王,女", "大王,男", "小白,男", "王小白,女"};
    
            //对字符串进行筛选,并返回需要的集合
            ArrayList<String> list = filter(str, (String str01) -> {
                return str01.split(",")[0].length() == 2;
            }, (str01) -> str01.split(",")[1].equals("女") );
    
    
            System.out.println(list);
        }
    }
    
    

    [小王,女]

    Function -数据类型转换接口


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

    • 抽象方法:apply,R apply,根据类型T的参数获取R型的结果,返回的是另一个类型的值。

    package cn.learn;
    
    
    import java.util.function.Function;
    
    public class function {
    
        public static Integer convert(String str, Function<String,Integer> function){
            //返回一个Integer类型
            return function.apply(str);
        }
    
        public static void main(String[] args) {
            String str = "2018";
            //调用convert方法转换类型,并用Lambda表达式重写apply方法
            Integer strInt = convert(str,(String str01) ->{
               return  Integer.parseInt(str01);
            });
    
            System.out.println(strInt);
        }
    }
    
    
    • 默认方法:andThen,用来进行组合操作

    • 需求:把字符串转换为Integer类型,把结果进行运算,
      再把整型转换回去

    package cn.learn;
    
    
    import java.util.function.Function;
    
    public class function {
    
        public static String convert(String str, Function<String,Integer> fun1,Function<Integer,String> fun2){
            //返回一个String类型
            return fun1.andThen(fun2).apply(str);
        }
    
        public static void main(String[] args) {
            String str = "2018";
            //调用convert方法转换类型,取出字符串对应的值并进行运算,再转换为String
            str = convert(str,str01 ->Integer.parseInt(str01)+10,int01 -> int01.toString());
            System.out.println(str);
        }
    }
    
    

    2028

  • 相关阅读:
    SpeedPHP多入口设置 前台和后台入口分开
    php重定向 htaccess文件的编写
    SpeedPHP关于一对一和一对多关联关系的建立 model建立
    SpringMVC与Struts2关于controller线程安全问题
    编码问题 关于hibernate jdbc数据库连接在xml配置与在properties文件配置的差异
    SpringMVC可以配置多个拦截后缀*.html和.do等
    JavaSE replaceAll 方法
    Promise.race 的原理
    Promise.all 的原理
    标签联合
  • 原文地址:https://www.cnblogs.com/huxiaobai/p/11621436.html
Copyright © 2011-2022 走看看