• jdk8中几个核心的函数式接口笔记


    1. Function接口

    /**
     * function 接口测试
     * function 函数只能接受一个参数,要接受两个参数,得使用BiFunction接口
     */
    public class FunctionTest {
    
    
        @Test
        public void Test (){
            FunctionTest test = new FunctionTest();
            // System.out.println(test.compute(4, x->x*2));
            System.out.println(test.compute(2, v -> v * 3, v -> v * v));
            System.out.println(test.compute2(2, v -> v * 3, v -> v * v));
    
            System.out.println(test.compute3(2,3, (a, b)-> a+b));
    
            System.out.println(test.compute4(2, 3, (a, b) -> a + b, a -> a * a));
        }
    
        /**
         * function的第一个参数是输入, 第二个参数是输出
         * @param a
         * @param function
         * @return
         */
        public int compute(int a, Function<Integer, Integer> function) {
            int result = function.apply(a);
            return result;
        }
    
        /**
         * compose 组合, 先执行传入的参数方法,再执行本身的方法
         * @param a 输入
         * @param func1 本身方法
         * @param func2 传入的参数方法
         * @return
         */
        public int compute(int a, Function<Integer, Integer> func1, Function<Integer, Integer> func2) {
            return func1.compose(func2).apply(a);
        }
    
        /**
         * andThen 方法,先执行自己的方法,再执行传入的参数方法
         * @param a
         * @param func1 本身方法
         * @param func2 传入的参数方法
         * @return
         */
        public int compute2(int a, Function<Integer, Integer> func1, Function<Integer, Integer> func2) {
            return func1.andThen(func2).apply(a);
        }
    
        /**
         * biFunction接口可传入两个参数
         * @param a
         * @param b
         * @param biFunction
         * @return
         */
        public int compute3(int a, int b, BiFunction<Integer, Integer, Integer> biFunction) {
            return biFunction.apply(a, b);
        }
    
        /**
         * biFunction只有一个andThen方法(参数还是Function),因为他只返回一个值,不能返回两个值
         * @param a
         * @param b
         * @param biFunction
         * @param function
         * @return
         */
        public int compute4(int a, int b, BiFunction<Integer, Integer, Integer> biFunction, Function<Integer, Integer> function) {
            return biFunction.andThen(function).apply(a,b);
        }
    }
    
    // 模仿Function接口, 接受一个参数, 返回一个值
    @FunctionalInterface
    interface FakeInterface<J, R> {
        R fuck(J t);
    }
    
    public class MyTest {
        public String myTest(Integer a, FakeInterface<Integer, String> fakeInterface) {
            System.out.println("执行我的fakeInterface中的方法, 传入一个参数");
            String s = fakeInterface.fuck(a);
            return s;
        }
    
        public static void main(String[] args) {
            MyTest myTest = new MyTest();
            String s = myTest.myTest(5, x -> String.valueOf(x));
            System.out.println(s);
        }
    }
    

    2. BiFunction接口

    public class PersonTest {
    
        @Test
        public void test1() {
            Person p1 = new Person("zhangsan", 20);
            Person p2 = new Person("lisi", 30);
            Person p3 = new Person("wangwu", 40);
            List<Person> persons = Arrays.asList(p1, p2, p3);
            PersonTest test = new PersonTest();
            List<Person> result = test.getPersonByAge(30, persons);
            result.forEach(x-> System.out.println(x.getUsername()));
        }
    
        @Test
        public void test2() {
            Person p1 = new Person("zhangsan", 20);
            Person p2 = new Person("lisi", 30);
            Person p3 = new Person("wangwu", 40);
            List<Person> persons = Arrays.asList(p1, p2, p3);
            PersonTest test = new PersonTest();
            List<Person> result = test.getPersonByAge2(30, persons, (age, personList) -> {
                return personList.stream().filter(p->p.getAge() > age).collect(Collectors.toList());
            });
            result.forEach(x-> System.out.println(x.getUsername()));
        }
    
        /**
         * 强行使用lamboda来写代码
         * @param age
         * @param persons
         * @return
         */
        public List<Person> getPersonByAge(int age, List<Person> persons) {
            // 定义函数操作
            BiFunction<Integer, List<Person>, List<Person>> biFunction =
                    (ageOfPerson, personList) ->
                    personList.stream().filter(person -> person.getAge()> ageOfPerson).collect(Collectors.toList());
            // 执行函数操作
            return biFunction.apply(age, persons);
         }
    
        /**
         * 不预先定义函数操作
         * @param age
         * @param persons
         * @param biFunction 函数操作由用户传入,更加灵活
         * @return
         */
        public List<Person> getPersonByAge2(int age, List<Person> persons, BiFunction<Integer, List<Person>, List<Person>> biFunction) {
            // 执行函数操作
            return biFunction.apply(age, persons);
        }
    

    3. Predicate接口

    import java.util.Arrays;
    import java.util.List;
    import java.util.function.Predicate;
    
    /**
     * predicate接口, 是一个根据给定参数来决定返回bool值的判断式函数式接口
     */
    public class PredicateTest {
    
        @Test
        public void Test1() {
            Predicate<String> predicate = p->p.length() > 5;
            System.out.println(predicate.test("hello"));
        }
    
        // 接口的简单练习
        @Test
        public void Test2() {
            List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
            PredicateTest predicateTest = new PredicateTest();
            System.out.println("打印出偶数: ");
            predicateTest.conditionFilter(list, item->(item & 1) == 0);
            System.out.println("---------------------------");
            System.out.println("打印出奇数: ");
            predicateTest.conditionFilter(list, item->(item & 1) == 1);
            System.out.println("---------------------------");
            predicateTest.conditionFilter(list, x->true);
            System.out.println("----------------------------");
            System.out.println("打印:, 大于5,并且偶数: ");
            predicateTest.conditionAndFilter(list, x -> x > 5, x -> (x & 1) == 0);
            System.out.println("----------------------------");
        }
    
        /**
         * 函数式编程的一大特点就是将行为提到方法外面,由用户传入
         * 调用时动态传入动作,更高层次的抽象化
         * @param list
         * @param predicate
         */
        public void conditionFilter(List<Integer> list, Predicate<Integer> predicate) {
            // 将通过条件判断的数字打印出来
            for (Integer i : list) {
                if (predicate.test(i)) {
                    System.out.println(i);
                }
            }
        }
    
        /**
         * predicate接口的 与 运算, 打印出符合两个条件的结果
         同理, 可理解predict中的其他逻辑运算
         * @param list
         * @param p1
         * @param p2
         */
        public void conditionAndFilter(List<Integer> list, Predicate<Integer> p1, Predicate<Integer> p2) {
            for (Integer i : list) {
                if (p1.and(p2).test(i)) {
                    System.out.println(i);
                }
            }
        }
    
        /**
         * Predicate.isEqual() 方法用于判断两个参数是否相同, 依据就是 Objects#equals(Object, Object)}.
         * 这个方法不怎么好理解, 说白了,就是调用传入参数的equals方法,
         * 得到其方法的引用,而这个引用又刚好符合Predict函数的格式,可以作为Predict来使用
         * @param object
         * @return
         */
        public Predicate<String> isEqual(Object object) {
            return Predicate.isEqual(object);
        }
    
        @Test
        public void Test3() {
            PredicateTest predicateTest = new PredicateTest();
            System.out.println(predicateTest.isEqual("test").test("test")); // true
            System.out.println(predicateTest.isEqual("test").test("test2")); // false
            System.out.println(predicateTest.isEqual(null).test("test")); // false
            System.out.println(predicateTest.isEqual(null).test(null)); //true
        }
    }
    

    4. Supplier接口

    @Data
    public class Student {
        private String name = "zhangsan";
        private Integer age = 20;
    }
    /**
     * Supplier接口, 不接受参数, 返回一个结果
     * 常用于 工厂
     * 
     */
    public class SupplierTest {
    
        // 最简单例子
        @Test
        public void Test() {
            Supplier<String> supplier = () -> "hello world";
            System.out.println(supplier.get());
        }
    
        /**
         * 利用supplier生产学生
         */
        @Test
        public void Test2() {
            Supplier<Student> supplier = ()->new Student();
            System.out.println(supplier.get().toString());
    
            // 更进一步, 调用Student的构造方法, 叫做构造方法的引用
            // 不接受参数, 返回Student对象,符合函数式接口的要求
            // 编译器会去Student找不带参数, 返回Student的构造方法
            Supplier<Student> supplier2 = Student::new;
            System.out.println(supplier2.get().toString());
        }
    }
    

    5. Consumer接口

    接收一个参数, 不返回值, 但可能改变传入的参数,通过这个改变的副作用来实现业务,list.forEach中就是一个Consumer接口作为参数

    list.forEach(x->System.out.println(x));
    
    default void forEach(Consumer<? super T> action) {
         Objects.requireNonNull(action);
            for (T t : this) {
                action.accept(t);
            }
    }
    
    public class MyTest {
        public void myTest2(Integer a, Consumer<Integer> consumer) {
            consumer.accept(a);
        }
    
        public static void main(String[] args) {
            MyTest myTest = new MyTest(); 
            myTest.myTest2(5, x-> {
                System.out.println("可以操作x,但没有返回值");
            });
        }
    }
    
  • 相关阅读:
    Java String 乱码
    HBase非原理性浅析
    git cherry-pick
    数据结构之队列
    数据结构之栈
    算法之简单排序
    数据结构之数组
    数据结构简介
    Java类型信息
    基数排序
  • 原文地址:https://www.cnblogs.com/Lothlorien/p/11992834.html
Copyright © 2020-2023  润新知