创建一个方法,接受可变长度的Function参数,可能有不同的类型

syn*_*gma 8 java lambda functional-programming java-8

假设我有一个字符串:String s = "1,2,3,4,5,6".我想创建一个方法combineFunctions(),将Functions 的可变长度序列作为参数,并按该顺序应用所有操作.

功能可以具有不同的<T,U>类型.

这种功能的示例用法如下:

Combine<String> c = new Combine<>(s);
List<String> numbers = c.combineFunctions(splitByComma);
Integer max = c.combineFunctions(splitByComma,convertToInt, findMax);
Run Code Online (Sandbox Code Playgroud)

我尝试了什么(<U>这里没有太多用处):

public <U> void combineFunctions(
        Function<? extends Object, ? extends Object>... functions) {

}
Run Code Online (Sandbox Code Playgroud)

但是我被困在获得最后一个Functions的类型.我也在考虑递归方法,但varargs参数必须是最后一个.

是否可以在Java中实现此类方法?

Tun*_*aki 3

这样的函数的问题是你失去了所有编译时类型检查并且强制转换是必要的。

这将是一个实现,用于andThen将功能组合在一起。由于所有的演员阵容,这看起来很难看,我不确定你能做得更正确。另请注意,这需要创建 2 个流管道,而实际上只需要 1 个。

public static void main(String[] args) throws Exception {
    String str = "1,2,3,4,5,6";
    Function<Object, Object> splitByComma = s -> ((String) s).split(",");
    Function<Object, Object> convertToInt = tokens -> Stream.of((String[]) tokens).map(Integer::valueOf).toArray(Integer[]::new);
    Function<Object, Object> findMax = ints -> Stream.of((Integer[]) ints).max(Integer::compare).get();
    Integer max = (Integer) combineFunctions(splitByComma, convertToInt, findMax).apply(str);
    System.out.println(max);
}

@SafeVarargs
private static Function<Object, Object> combineFunctions(Function<Object, Object>... functions) {
    return Arrays.stream(functions)
                 .reduce(Function::andThen)
                 .orElseThrow(() -> new IllegalArgumentException("No functions to combine"));
}
Run Code Online (Sandbox Code Playgroud)

为了匹配您问题中的代码,您可以将其包装到一个类中,如下所示:

public class Combiner<R> {

    private Object input;

    public Combiner(Object input) {
        this.input = input;
    }

    @SuppressWarnings("unchecked")
    @SafeVarargs
    public final R combineFunctions(Function<Object, Object>... functions) {
        return (R) Arrays.stream(functions)
                         .reduce(Function::andThen)
                         .orElseThrow(() -> new IllegalArgumentException("No functions to combine"))
                         .apply(input);
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 如果您接受类型安全性的缺乏,您可以像“Object o=input;”一样实现“combineFunctions”方法。for(函数 f: 函数) o=f.apply(o); return o;` 但目前还不清楚为什么你认为你需要这个...... (3认同)