• 21.函数式接口


    函数式接口

    概述

    函数式接口: 有且仅有一个抽象方法的接口

    java中的函数式变成体现的就是Lambda表达式, 所以函数式接口就是可以适用于lambda使用的接口

    只有确保接口中有且仅有一个抽象方法, java中的lambda才能顺利进行推导

    MyInterface

    package functionInterface;
    @FunctionalInterface  // 函数式接口, 有且只有一个抽象方法; 但只有一个抽象方法的时候, 默认为函数式接口
    public interface MyInterface {
        void show();
    }
    

    MyInterfaceDemo

    package functionInterface;
    
    public class MyInterfaceDemo {
        public static void main(String[] args) {
            MyInterface my = () -> System.out.println("函数式接口");
    
            my.show();
        }
    }
    

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

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

    • startThread(() -> System.out.println(Thread.currentThread().getName() + "线程启动了"));

    RunnableDemo

    package functionInterface.demo2;
    
    public class RunnableDemo {
        public static void main(String[] args) {
            // 调用startThread方法
            startThread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + "线程启动了");
                }
            });
    
            // lambda表达式实现
            startThread(() -> System.out.println(Thread.currentThread().getName() + "线程启动了"));
        }
    
        private static void startThread(Runnable r) {
            new Thread(r).start();
        }
    }
    

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

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

    ComparatorDemo

    package functionInterface.demo3;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    
    public class ComparatorDemo {
        public static void main(String[] args) {
            ArrayList<String> array = new ArrayList<String>();
            array.add("cccc");
            array.add("aa");
            array.add("b");
            array.add("ddd");
    
            System.out.println("排序前: " + array);
            // Collections.sort(array);
            Collections.sort(array, getComparator());
            System.out.println("排序后: " + array);
        }
    
        private static Comparator<String> getComparator() {
            // 匿名内部类
            /*
            return new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    return o1.length() - o2.length();
                }
            };
             */
    
            // lambda表达式实现
            /*
            return (String s1, String s2) -> {
                return s1.length() - s2.length();
            };
             */
            return (s1, s2) -> s1.length() - s2.length();
        }
    }
    

    常用的函数式接口

    java8预定义了大量函数式接口, 常用如下

    • Supplier接口

    • Consumer接口

    • Predicate接口

    • Function接口

    Supplier接口

    Supplier: 包含一个无参的方法

    • T get(): 获得结果

    • 该方法不需要参数, 她会按照某种实现逻辑(由lambda表达式实现) 返回一个数据

    • Supplier接口也被称为生产型接口, 如果我们指定了接口的泛型是什么类型, 那么接口中get方法就会产生什么类型的数据供我们使用

    SupplierDemo

    package functionInterface;
    
    import java.util.function.Supplier;
    
    public class SupplierDemo {
        public static void main(String[] args) {
            /*
            String s = getString(() -> {
                return "林青霞";
            });
             */
    
            String s = getString(() -> "林青霞");
            System.out.println(s);
    
            Integer i = getInteger(() -> 30);
            System.out.println(i);
        }
    
        // 定义一个返回字符串的方法
        private static String getString(Supplier<String> sup) {
            return sup.get();
        }
    
        // 定义一个返回整数的方法
        private static Integer getInteger(Supplier<Integer> sup) {
            return sup.get();
        }
    }
    

    例子

    package functionInterface;
    
    import java.util.function.Supplier;
    
    public class SupplierDemo2 {
        public static void main(String[] args) {
            // 定义int数组
            int[] arr = {19, 50, 28, 37, 46};
            int maxValue = getMax(() -> {
                int max = arr[0];
                for (int i=1; i<arr.length; i++) {
                    if(arr[i] > max) {
                        max = arr[i];
                    }
                }
                return max;
            });
            System.out.println(maxValue);
    
        }
    
        // 返回一个int数组中的最大值
        private static int getMax(Supplier<Integer> sup){
            return sup.get();
        }
    }
    

    Consumer接口

    Consumer: 包含两个方法

    • void accept(T t): 对给定的参数执行此操作

    • defaultConsumer andThen(Consumer after): 返回一个组合的Consumer, 依次执行此操作, 然后执行after操作

    • Consumer: 接口也被称为消费型接口, 它消费的数据的数据类型由泛型指定

    ConsumerDemo

    package functionInterface;
    
    import java.util.function.Consumer;
    
    public class ConsumerDemo {
        public static void main(String[] args) {
            /*
            operatorString("林青霞", (String s) -> {
                System.out.println(s);
            });
             */
            // 优化
            operatorString("林青霞", s -> System.out.println(s));
            // operatorString("林青霞", System.out::println);
    
            operatorString("林青霞", s -> {
                System.out.println(new StringBuilder(s).reverse().toString());
            });
    
            System.out.println("--------");
            operatorString("林青霞",s -> System.out.println(s), s -> System.out.println(new StringBuilder(s).reverse().toString()));
        }
    
        //定义方法消费字符串
        private static void operatorString(String name, Consumer<String> con) {
            con.accept(name);
        }
        // 定义一个方法, 用不同方式消费同一个字符串两次
        private static void operatorString(String name, Consumer<String> con1, Consumer<String> con2) {
            // con1.accept(name);
            // con2.accept(name);
            con1.andThen(con2).accept(name);
        }
    }
    

    示例

    package functionInterface;
    
    import java.util.function.Consumer;
    
    public class ConsumerDemo2 {
        public static void main(String[] args) {
            String[] strArray = {"林青霞,30", "张曼玉,35", "王祖贤,33"};
    
            printInfo(strArray, (String str) -> {
                String name = str.split(",")[0];
                System.out.print("姓名: " + name);
            }, (String str) -> {
                int age = Integer.parseInt(str.split(",")[1]);
                System.out.println(", 年龄: " + age);
            });
     
            // 优化
            printInfo(strArray, str -> System.out.print("姓名: " + str.split(",")[0]),
                    str -> System.out.println(", 年龄: " + Integer.parseInt(str.split(",")[1])));
        }
    
        private static void printInfo(String[] strArray, Consumer<String> con1, Consumer<String> con2) {
            for(String str: strArray) {
                con1.andThen(con2).accept(str);
            }
        }
    }
    

    Predicate接口

    Predicate: 常用四个方法

    变量和类型 方法 描述
    boolean test(T t) 根据给定的参数计算此谓词, 判断逻辑有lambda表达式实现, 返回一个布尔值
    default Predicate<T> and(Predicate<? super T> other) 返回一个组合谓词,表示此谓词和另一个谓词的短路逻辑AND。
    default Predicate<T> negate() 返回一个逻辑的否定, 对应逻辑非
    default Predicate<T> or(Predicate<? super T> other) 返回一个组合谓词,表示此谓词与另一个谓词的短路逻辑OR。
    Predicate 接口通常用于判断参数是否满足指定条件

    PredicateDemo

    package functionInterface;
    
    import java.util.function.Predicate;
    
    public class PredicateDemo {
        public static void main(String[] args) {
            // diaoyogn
            /*
            boolean b1 = checkString("hello", (String s) -> {
                return s.length() > 8;
            });
             */
    
            boolean b1 = checkString("hello", s -> s.length() > 8);
            System.out.println(b1);
    
            boolean b2 = checkString("helloworld", s -> s.length() > 8);
            System.out.println(b2);
    
            boolean b3 = checkString("hello", s -> s.length() > 8, s -> s.length()<15);
            System.out.println(b3);
    
            boolean b4 = checkString("helloworld", s -> s.length()>8, s -> s.length()<15);
            System.out.println(b4);
        }
    
        // 判断给定字符串是否满足要求
        private static boolean checkString(String s, Predicate<String> pre) {
            // return pre.test(s);
            // return !pre.test(s);
            return pre.negate().test(s);
        }
    
        // 同一个字符串给出两个不同的判断条件, 最后将这两个接口做逻辑与运算的结果作为最终结果
        private static boolean checkString(String s, Predicate<String> pre1, Predicate<String> pre2) {
            /*
            boolean b1 = pre1.test(s);
            boolean b2 = pre2.test(s);
            boolean b = b1 && b2;
            return b;
             */
            // return pre1.and(pre2).test(s);
            return pre1.or(pre2).test(s);
        }
    }
    

    例子

    package functionInterface.demo3;
    
    import java.util.ArrayList;
    import java.util.function.Predicate;
    
    public class PredicateDemo2 {
        public static void main(String[] args) {
            String[] strArray = {"林青霞,30", "柳岩,34","张曼玉,35","貂蝉,31","王祖贤,33"};
            ArrayList<String> array = myFilter(strArray, s -> s.split(",")[0].length()>2,
                    s -> Integer.parseInt(s.split(",")[1])>33);
            for(String str: array){
                System.out.println(str);
            }
        }
    
        // 通过Predicate的拼装, 将符合要求的字符串筛选到ArrayList中
        private static ArrayList<String> myFilter(String[] strArray, Predicate<String>pre1, Predicate<String> pre2) {
            // 定义集合
            ArrayList<String> array = new ArrayList<String>();
            // 遍历数组
            for(String str: strArray) {
                if(pre1.and(pre2).test(str)) {
                    array.add(str);
                }
            }
            return array;
        }
    }
    

    Function接口

    Function<T, R>: 常用方法

    • R apply(T t): 将此函数作用于给定的参数

    • default Function andThen(Function after): 返回一个组合函数, 首先将该函数引用于输入, 然后将after函数应用于结果.

    • Function<T, R>接口通常用于对参数进行处理, 转换(处理逻辑由Lambda表达式实现), 然后返回一个新的值

    FunctionDemo

    package functionInterface;
    
    import java.util.function.Function;
    
    public class FunctionDemo {
        public static void main(String[] args) {
            convert("100", s -> Integer.parseInt(s));
            convert("100", Integer::parseInt);
    
            // 需求2:
            convert(100, i -> String.valueOf(i + 566));
    
            // 需求3:
            convert("100", s -> Integer.parseInt(s), i -> String.valueOf(i + 566));
        }
    
        // 定义一个方法, 将字符串转为int类型, 在控制台输出
        private static void convert(String s, Function<String ,Integer> fun) {
            int i = fun.apply(s);
            System.out.println(i);
        }
    
        // 定义一个方法, 将int类型的数据加上一个整数后, 转为字符串输出
        private static void convert(int i, Function<Integer, String> fun) {
            String s = fun.apply(i);
            System.out.println(s);
        }
    
        // 定义一个方法, 将字符串转为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);
        }
    }
    

    例子

    package functionInterface;
    
    import java.util.function.Function;
    
    public class FunctionDemo2 {
        public static void main(String[] args) {
            String s = "林青霞,30";
            convert(s, (String ss) -> {
                return s.split(",")[1];
            }, (String ss) -> {
                return Integer.parseInt(ss);
            }, (Integer i) -> {
                return i + 70;
            });
    
            convert(s, ss -> s.split(",")[1], ss -> Integer.parseInt(ss), i -> i + 70);
    
            // 方法引用
            convert(s, ss -> s.split(",")[1], Integer::parseInt, i -> i + 70);
        }
    
        private static void convert(String s, Function<String, String> fun1, Function<String, Integer> fun2, Function<Integer, Integer> fun3) {
            Integer i = fun1.andThen(fun2).andThen(fun3).apply(s);
            System.out.println(i);
        }
    }
    
  • 相关阅读:
    python装饰器的作用
    python的__call__、__str__、__repr__、__init__、__class__、__name___、__all__、__doc__、__del__等魔术方法的作用
    安全小测试:介绍一个简单web安全知识测试的网站
    浏览器都知道我们的哪些信息?
    SQL开发技巧(二)
    如何解决SQLServer占CPU100%
    记一次SQLServer的分页优化兼谈谈使用Row_Number()分页存在的问题
    如何在SQLServer中处理每天四亿三千万记录
    SqlServer索引的原理与应用
    T-sql语句查询执行顺序
  • 原文地址:https://www.cnblogs.com/ryxiong-blog/p/13890488.html
Copyright © 2020-2023  润新知