高级函数特性

211 阅读2分钟

1 复合函数和函数柯里化

public interface Function<R, I> {

    R apply(I a);
}

1.1 引入

使用上面的Function,定义一个函数,用于对两个整数求和。


@Test
public void test1() {
    Function<Function<Integer,Integer>,Integer> add = a -> b -> a +b;
    Integer apply = add.apply(3).apply(5);
    System.out.println(apply); // 8

}

下面来进行一步步函数推导

  1. 根据需求计算两个数的和(函数add(a,b) = a + b)

  2. 先把函数作用于a,返回的是一个函数f(b) = a + b

    1. add(a) = g(b)
    2. g(b) = a + b
  3. 所以函数add函数可以推导出类型为:

Function<Function<Integer,Integer>,Integer> add

结合下面匿名函数方式实现,进行理解

add = new Function<Function<Integer, Integer>, Integer>() {
    @Override
    public Function<Integer, Integer> apply(Integer a) {
        return new Function<Integer, Integer>() {
            @Override
            public Integer apply(Integer b) {
                return a + b;
            }
        };
    }
};

Function<Integer, Integer> apply1 = add.apply(3);
apply1.apply(5);

为了在理解一下函数推导和柯里化,在做一个练习 将两个Function函数进行复合,比如先计算 (a+2)的平方,就可以拆成两个函数

f(x) = x^2;  g(x) = x+2

f(g(x)) = (x+2)^2f(g(x)) 为定义为compose(x)
compose(x) = f(g(x)) 

上面这只是数学上分析和推导,现在就是用Function来实现这个需求

  1. 明确Function的泛型,也就是输入和输出
    1. 接受一个函数,就是上面的g(x),g(x)本身就是计算 x+2,也就是说 g(x) 用Function表示就是
    Function<Integer,Integer>
    
    1. 返回也是一个函数,也就是f(x), f(x)接受的是一个g(x) 返回值依然是个函数:
    Function<Function<Integer,Integer>,Function<Integer,Integer>>
    

到此明确了compose的类型就是:

Function<
    Function<Function<Integer,Integer>,Function<Integer,Integer>>,
     Function<Integer,Integer>
    >

实现:

Function<
    Function<Function<Integer,Integer>,Function<Integer,Integer>>,
    Function<Integer,Integer>
    > compose = null;
    
// 1 g: 表示g(x),类型为Function<Integer,Integer>
// 2 f: 表示是f(x),类型为Function<Integer,Integer>
// 3 a: 表示入参是a,是Integer类型
// 4 最后一部分就是整个compose的定义就是先执行g(x), 在执行f(x)
compose = g -> f -> a -> f.apply(g.apply(a));

测试:

@Test
public void test2() {
    Function<Integer,Integer> add = a -> a + 2;
    Function<Integer,Integer> square = a -> a * a;

    /**
     * 组合两个Function
     */
    Function<
            Function<Function<Integer,Integer>,Function<Integer,Integer>>,
            Function<Integer,Integer>
            >
    // 接受的就是函数
    compose = g -> f -> a -> f.apply(g.apply(a));
    Integer apply = compose.apply(add).apply(square).apply(3);
    System.out.println(apply); // 3
}

为了通用,显然参数需要泛型化,但是java只能在接口类或者方法上进行泛型化,所以: