zoukankan      html  css  js  c++  java
  • 学习笔记之函数式接口

    函数式接口

    概述

    1. 函数式接口:有且仅有一个抽象方法的接口
      java中的函数式编程体现就是Lambda表达式,所以函数式接口就是可以适用于Lambda使用的接口,只有确保接口中有且仅有一个抽象方法,java中的Lambda才能顺利进行推导
    2. 检测一个接口是否是函数式接口
      • @FunctionalInterface
      • 放在接口定义的上方:如果接口是函数式接口,编译通过;反之,编译失败

    定义函数式接口时,@FunctionalInterface可选,就算不写,只要保证满足函数式接口定义条件,也照样是函数式接口(建议加上该注解)。

    函数式接口作为方法的参数

    需求:

    • 定义一个(Demo),在类中提供两个方法
      1. startThread(Runnable r)方法参数Runnable是一个函数式接口
      2. 主方法,调用startThread方法
    public class Demo {
        public static void main(String[] args) {
            startThread(() -> System.out.println(Thread.currentThread().getName()+"线程启动了"));
        }
        private static void startThread(Runnable r){
            new Thread(r).start();
        }
    }
    

    如果方法的参数是一个函数式接口,可以使用Lambda表达式作为参数传递

    函数式接口作为接口的返回值

    需求:

    • 定义一个类(Demo),在类中提供两个方法
      1. CompartorgetCompartor()方法的返回值式Commpartor是一个函数式接口
      2. 主方法调用getCommparator方法
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    
    public class Demo {
        public static void main(String[] args) {
            ArrayList<String> a = new ArrayList<>();
            a.add("cc");
            a.add("aaaaa");
            a.add("bbb");
            Collections.sort(a,getCommparator());
            System.out.println(a);
        }
        private static Comparator<String> getCommparator(){
            //方法1
    //        Comparator<String> c = new Comparator<String>() {
    //            @Override
    //            public int compare(String s, String t1) {
    //                return s.length() - t1.length();
    //            }
    //        };
    //        return c;
    
            //方法2
    //        return new Comparator<String>() {
    //            @Override
    //            public int compare(String s, String t1) {
    //                return s.length() - t1.length();
    //            }
    //        }
    
            //方法3
            return ( s1, s2) -> s1.length() -s2.length();
        }
    }
    

    如果方法的返回值式一个函数式接口,我们可以使用Lambda表达式结果返回

    常用的函数是接口

    java 8在java.util.function包下预定义了大量的函数式接口
    如:

    1. Supplier接口
    2. Consumer接口
    3. Predicate接口
    4. Function接口
      等等
    Supplier
    • Supplier:包含一个无参的方法
      • T get():获得结果
      • 该方法不需要参数,它会按照某种实现逻辑(由Lambda表达式实现)返回一个数据
      • Supplier接口也被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会产生什么类型的数据供我们使用
    import java.util.function.Supplier;
    
    public class Demo {
        public static void main(String[] args) {
            String s = getString(() -> "Hello,World");
            System.out.println(s);
    
            Integer i = getIneger(() -> 5);
            System.out.println(i);
        }
    
        private static int getIneger(Supplier<Integer> s) {
            return s.get();
        }
    
        private static String getString(Supplier<String> s) {
            return s.get();
        }
    }
    

    Supplier练习
    • 定义一个类(SupplierTest),在类中提供两个方法
      1. int getMax(Supplier s)用于返回一个int数组中的最大值
      2. 主方法调用getMax方法
    import java.util.Arrays;
    import java.util.function.Supplier;
    
    public class SupplierTest {
        public static void main(String[] args) {
            int[] i = {1, 2, 3, 52, 68, 45};
            int IntegerMax = getMax(() -> {
                        Arrays.sort(i);
                        return i[i.length - 1];
                    }
            );
            System.out.println(IntegerMax);
        }
    
        private static int getMax(Supplier<Integer> s) {
            return s.get();
        }
    }
    

    Consumer
    • Consumer:包含两个方法
      • void accept(T t):对给定的参数执行此操作
      • default Consumer andThe(Consumer after):返回一个组合的Consumer,一次执行此操作,然后执行after操作
      • Consumer接口也被称为消费型接口,它消费的数据的类型由泛型指定
    import java.util.function.Consumer;
    
    public class ConsumerDemo {
        public static void main(String[] args) {
            //Lambda表达式
            operatorString("Hello,World",s-> System.out.println(s));
            //方法引用
            operatorString("Hello,World",System.out::println);
    
        }
        private static void operatorString(String n, Consumer<String> c){
            c.accept(n);
        }
    }
    
    Consumer练习
    • String [] strArray = {"张三,18","李四,20","王五,19"}
    • 字符串数组中有多条信息,请按照格式:"姓名:XX,年龄:XX"的格式将信息打印出来
    • 需求:
      • 把打印姓名的动作作为一个Consumer接口的Lambda实例
      • 把打印年龄的动作作为第二个Consumer接口Lambda实例
      • 将两个Consumer接口按照顺序组合到一起
    import java.util.function.Consumer;
    
    public class ConsumerTest {
        public static void main(String[] args) {
            String [] strArray = {"张三,18","李四,20","王五,19"};
    //        operatorConsumer(strArray,s -> {
    //            String name = s.split(",")[0];
    //            System.out.print("姓名:"+name);
    //        },s -> {
    //        int age = Integer.parseInt(s.split(",")[1]);
    //            System.out.println(",年龄:"+age);
    //        });
            operatorConsumer(strArray,
                    s -> System.out.print("姓名:"+s.split(",")[0]),
                    s -> System.out.println(",年龄:"+Integer.parseInt(s.split(",")[1])));
        }
        private static void operatorConsumer(String [] strArray, Consumer<String> c1, Consumer<String> c2){
            for (String i:strArray){
                c1.andThen(c2).accept(i);
            }
        }
    }
    

    Predicate接口
    • predicate:常用的四个方法
      1. boolean test(T t):对给定的参数进行判断(判断逻辑有Lambda表达式实现,返回一个布尔值)
      2. default Predicate negate():返回一个逻辑的否定,对应逻辑非
      3. default Predicate and(Predicate other):返回一个组合判断,对应短路与
      4. default Predicate or(Predicate other):返回一个组合判断,对应短路或
    • Predicate接口通常用于判断参数是否满足指定条件

    test方法与negate方法:

    import java.util.function.Predicate;
    public class PredicateDemo {
        public static void main(String[] args) {
            boolean b1 = checkString("hello", s -> s.length() > 8);
            System.out.println(b1);
    
            boolean b2 = checkString("hello", s -> s.length() < 8);
        }
    
        //判断给定字符串是否满足要求
        private static boolean checkString(String s, Predicate<String> p) {
    //        return p.test(s);
    //        return !p.test(s);
            return p.negate().test(s);
        }
    }
    

    and方法与or方法:

    import java.util.function.Predicate;
    
    public class PredicateDemo2 {
        public static void main(String[] args) {
            boolean b1 = checkString("hello", s -> s.length() > 8);
            System.out.println(b1);
    
            boolean b2 = checkString("hello", s -> s.length() < 8);
            System.out.println(b2);
    
            boolean b3 = checkString("hello", s -> s.length() > 8, s -> s.length() < 8);
            System.out.println(b3);
        }
    
        //判断给定字符串是否满足要求
        private static boolean checkString(String s, Predicate<String> p) {
            return p.test(s);
        }
    
        //同一个字符串给出两个不同的判断条件,最后把这两个判断条件结果做逻辑与运算的结果作为最终的结果
        private static boolean checkString(String s, Predicate<String> p, Predicate<String> p2) {
    //        return p.and(p).and(p2).test(s);   //false
            return p.or(p).or(p2).test(s);      //true
        }
    }
    
    Predicate练习
    • String[] strArray = {"张三,18","李四,20","王五,19","王麻子,21","张三丰,17"}
    • 字符串数组中有多条信息,请通过Predicate接口的拼接将符合要求的字符串选到集合ArrayList中,并遍历ArrayList集合
    • 同时满足如下要求:姓名长度大于2;年龄大于19
    • 分析
      • 有两个判断条件,所以需要使用两个Predicate接口,对条件进行判断
      • 必须同时满足两个条件,所以可以使用and方法连接两个判断条件
    import java.util.ArrayList;
    import java.util.function.Predicate;
    public class PredicateTest {
        public static void main(String[] args) {
            String[] strArray = {"张三,18", "李四,20", "王五,19", "王麻子,21", "张三丰,17"};
    
            ArrayList<String> array = myFilter(strArray,
                    s -> s.split(",")[0].length() > 2,
                    s -> Integer.parseInt(s.split(",")[1]) > 19);
            for (String i : array){
                System.out.println(i);
            }
        }
    
        private static ArrayList<String> myFilter(String[] strArray, Predicate<String> p1, Predicate<String> p2) {
            ArrayList<String> array = new ArrayList<>();
            for (String i : strArray) {
                if (p1.and(p2).test(i)) {
                    array.add(i);
                }
            }
    
            return array;
        }
    }
    
    Function接口

    常用方法:

    • R apply​(T t)将此函数应用于给定的参数。
    • default Function<T,V> andThen​(Funcation after):返回一个组合函数,首先将该函数应用于其输入,然后将 after函数应用于结果。
    • Funcation<T,R>接口通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值
    import java.util.function.Function;
    public class Demo {
        public static void main(String[] args) {
            Convert("50", s -> Integer.parseInt(s));
            Convert("100", Integer::parseInt);
    
            Convert(100, i -> String.valueOf(i + 20));
    
            Convert("66", s -> Integer.parseInt(s), i -> String.valueOf(i+30));
        }
    
        //定义一个方法,把一个字符串转换int类型,控制台输出
        private static void Convert(String s, Function<String, Integer> fun) {
            int apply = fun.apply(s);
            System.out.println(apply);
        }
    
        //定义一个方法,把一个int类型的数据加上一个整数之后,转为字符串在控制台输出
        private static void Convert(int i, Function<Integer, String> fun) {
            String s = fun.apply(i);
            System.out.println(s);
        }
    
        //定义一个方法,把一个字符串转换int类型,把int类型的数据加上一个整数之后,
        // 转换字符串在控制台输出
        private static void Convert(String s, Function<String, Integer> fun1, Function<Integer, String> fun2) {
    //        Integer i = fun1.apply(s);
    //        String ss = fun2.apply(i);
    //        System.out.println(ss);
    
            String ss = fun1.andThen(fun2).apply(s);
            System.out.println(ss);
        }
    }
    
    练习
    • String = "张三, 20"
    • 操作
      1. 将字符串截取得到年龄部分
      2. 将上一步得年龄转换成为int类型的数据
      3. 将上一步的int数据加10,得到一个int结果,在控制台输出
    • 使用Funcation实现
    
    import java.util.function.Function;
    
    public class Demo {
        public static void main(String[] args) {
            Convert("张三,20",s -> s.split(",")[1],s -> Integer.parseInt(s),i -> (i+10));
    
        }
        private static void Convert(String s, Function<String,String> fun1,Function<String,Integer> fun2,Function<Integer,Integer> fun3){
            int i = fun1.andThen(fun2).andThen(fun3).apply(s);
            System.out.println(i);
        }
    }
    
  • 相关阅读:
    Java实验项目六——使用DAO模式实现对职工表的操作
    Java实验项目三——职工类对象数组按照职工生日排序
    Java实验项目三——编程实现Person类,学生类的设计及其继承关系
    Java实验项目三——平面图形和立体图形抽象类
    javax.naming.NoInitialContextException:Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
    对实体 "useSSL" 的引用必须以 ';' 分隔符结尾。
    MATLAB自定义配置
    POJ 2976 Dropping tests(最大化平均值 or 01整数规划)
    POJ3273 Monthly Expense
    POJ3258 River Hopscotch
  • 原文地址:https://www.cnblogs.com/Hz-z/p/13086999.html
Copyright © 2011-2022 走看看