Java8新特性-002-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;
    }
}

案例

public class FunctionTest {


    public static void main(String[] args) {
        FunctionTest functionTest = new FunctionTest();

        //同一个方法,传递不同的行为,获取不同的结果
        //用户使用的时候,决定传递什么行为
        System.out.println(functionTest.compute(1,arg -> 2*arg));
        System.out.println(functionTest.compute(1,arg -> 5+arg));
        System.out.println(functionTest.compute(1,arg -> arg*arg));
    }


    /**
     * 
     * @param a 输入参数
     * @param function 计算结果的函数
     * @return 计算结果
     */
    public int compute(Integer a, Function<Integer,Integer> function){

        Integer result = function.apply(a);
        
        return result;
    }
    
}

高阶函数

  • 如果一个函数接受一个函数作为参数,或者返回一个函数作为返回值,那么该函数就叫做高阶函数。

默认方法,组合函数

compose

  • 代码
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }
    
  • 在执行此次Function的apply方法之前,执行before的apply方法,获取结果之后,再执行此次的function的apply方法
    1. re = before.apply(v)
    2. 最后的结果 = this.apply(re)
    
  • 目的:其他function的apply优先执行,执行完,执行自身的apply方法

andThen

  • 代码
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }
    
  • 解释:与上面的compose相比,也是可以依次执行多个function,但是,本身function的apply先执行,然后再之前,参数中即后面的function的apply方法。
    1. re = this..apply(v)
    2. 最后的结果 = after.apply(re)
    

identify

  • 代码
    static <T> Function<T, T> identity() {
        return t -> t;
    }
    
  • 解释:返回自身的function,那么用途呢???,后续看开发情况,Function.identify()用于输入一个请求,然后原始请求,不进行改变,用途呢,类似于,如果一个List要根据某个字段进行转换成map,
    
    

案例

  • 代码
    public class FunctionInnerMethodTest {
    
    
        public static void main(String[] args) {
    
            FunctionInnerMethodTest test = new FunctionInnerMethodTest();
            System.out.println(test.compute(3,a->a+2,a->a*a));//11
            System.out.println(test.compute2(3,a->a+2,a->a*a));//25
        }
    
    
        public int compute(int a, Function<Integer,Integer> function1,Function<Integer,Integer> function2){
            return function1.compose(function2).apply(a);
        }
    
        public int compute2(int a, Function<Integer,Integer> function1,Function<Integer,Integer> function2){
            return function1.andThen(function2).apply(a);
        }
    }
    
  • 理解一波:内部的compose和andThen实质是生成一个新的Function这个function内部有自己执行的逻辑,这个逻辑正式function1和function2的执行逻辑,所以function1.componse(function2)是一个新的function所以可以再次执行apply方法,然后参数会在内部进行重新执行。
  • 但是如果需要进行多个参数呢??显然function无法解决,那么jdk就有,两个入参一个返回的函数式接口BiFunction

BiFunction

  • 代码类似,只是传递了两个参数,一个返回值
    @FunctionalInterface
    public interface BiFunction<T, U, R> {
    
        R apply(T t, U u);
    
        //先执行biFunction的apply,然后将结果使用到function中
        default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
            Objects.requireNonNull(after);
            return (T t, U u) -> after.apply(apply(t, u));
        }
    }
    
  • 解释:T,U为输入两个参数的类型,R为结果类型

示例

  • 代码:需求:增加一个两个参数进行加减乘除的计算,之前是写4个方法,现在使用biFuntion,传入进行四则预算的行为,来进行抽象方法。
    public class FunctionInnerMethodTest {
    
    
        public static void main(String[] args) {
    
            FunctionInnerMethodTest test = new FunctionInnerMethodTest();
        
            System.out.println(test.compute3(4,2,(a,b)->a+b));//6
            System.out.println(test.compute3(4,2,(a,b)->a-b));//2
            System.out.println(test.compute3(4,2,(a,b)->a*b));//8
            System.out.println(test.compute3(4,2,(a,b)->a/b));//2
        }
    
        public int compute3(int a, int b, BiFunction<Integer,Integer,Integer> biFunction){
            return biFunction.apply(a,b);
        }
    }
    
    
  • 需求,一个list获取某个条件过滤之后的list
    public class BiFunctionDemo {
    
    
        public static void main(String[] args) {
    
            List<Person> people = Arrays.asList(new Person().setAge(1).setName("张三"),
                    new Person().setAge(2).setName("李四"),
                    new Person().setAge(3).setName("王五"));
    
            BiFunctionDemo demo = new BiFunctionDemo();
    
            //获取年龄为1的list
            System.out.println(demo.getPersonListByAge(1,people));
            System.out.println("-----------------");
    
            //获取姓名为张三的List
            System.out.println(demo.getPersonListByName("张三",people));
            System.out.println("-----------------");
    
            //通过lambda表达式传入行为,获取某种行为的List,可以看出更加灵活
            System.out.println(demo.getPersonListByOptions(2,people,
                    (age,list)->list.stream().filter(person -> person.getAge().equals(age)).collect(Collectors.toList())));
    
            System.out.println(demo.getPersonListByOptions("王五",people,
                    (name,list)->list.stream().filter(person -> person.getName().equals(name)).collect(Collectors.toList())));
    
        }
    
    
        public List<Person> getPersonListByAge(Integer age,List<Person> list){
            return list.stream().filter(person -> person.getAge().equals(age)).collect(Collectors.toList());
        }
    
    
    
        public List<Person> getPersonListByName(String name,List<Person> list){
    
            BiFunction<String,List<Person>,List<Person>> biFunction
                    = (personName,personList)->personList.stream().filter(person -> person.getName().equals(name))
                    .collect(Collectors.toList());
    
            return biFunction.apply(name,list);
        }
    
    
        //传递特定的行为,通过泛型,更加灵活
        public <T> List<Person> getPersonListByOptions(T val, List<Person> list,
                                               BiFunction<T,List<Person>,List<Person>> biFunction){
            return biFunction.apply(val,list);
        }
    
    
        
    
        @Data
        @Accessors(chain = true)
        static class Person{
            private Integer age;
            private String name;
        }
    }
    
©️2020 CSDN 皮肤主题: 像素格子 设计师:CSDN官方博客 返回首页