结合不同类型的函数

Combining funtions with different types

我正在编写一个方法,该方法在参数上执行可变的 lambda 列表:

public class Main {
    static public<T, R> R convertBy(T data, Function... f) {
        Function composer = Function.identity();
        for (var fi: f ) {
            composer = composer.andThen(fi);
        }

        return (R)composer.apply(data);
    }

     public static void main(String[] args) {
        Function<String, String> l1 = x -> x.toLowerCase(Locale.ROOT);
        Function<String, Integer> l2 = String::length;

        Integer ret = convertBy("Lorem ipsum", l1, l2);
      }
}

有没有办法使用模板而不是原始函数? 我的意思是使用模板表达这种转换的某种方式:T -> ... -> R。或者至少在 return.

中摆脱对 R 的转换

你不能用可变参数来做到这一点,因为你需要所有的函数都是相同的类型:这意味着所有的函数都必须有相同的输入和输出类型,以便一个调用的输出可以作为下一个调用的输入。

换句话说,R必须等于T

static public<T> T convertBy(T data, Function<T, T>... fs) { ... }

您可以假装通过提供大量重载来支持可变参数,对于 1、2、3、... N 种情况:

static public<T0, T1> T1 convertBy(T0 data, Function<T0, T1> f0) { ... }
static public<T0, T1, T2> T2 convertBy(T0 data, Function<T0, T1> f0, Function<T1, T2> f1) { ... }
static public<T0, T1, T2, T3> T3 convertBy(T0 data, Function<T0, T1> f0, Function<T1, T2> f1, Function<T2, T3> f2) { ... }

这显然涉及相当多的代码重复。 (这方面有现有技术,例如 List.of methods

但除此之外,没有什么好的表达方式type-safe

但是,因为这些实际上 可变参数方法,所以您不能使用函数数组调用它们。鉴于此,拥有所有这些重载没有多大意义,因为您可以只使用 andThen 来链接函数;然后只需使用 apply 方法:

T result = f0.andThen(f1).andThen(f2).apply(data);