我们说我有一些lambda表达式如下:
Function<String, List<String>> flines = fileName -> {
//Puts all lines from file into List and returns a list
};
Function<List<String>, String> join = listOfLines -> {
//Concatenates all lines from list and returns them as String
};
Function<String, List<Integer>> collectInts = str -> {
//Returns all Integer occurences from given String
};
我想创建一个函数,让我们说resultType convertBy(Function<T,S>...args)
所以我可以组合参数并返回结果:
List<String> lines = fileConv.convertBy(flines) //returns list of lines
String text = fileConv.convertBy(flines, join); //returns s String from concatenated Strings
List<Integer> ints = fileConv.convertBy(flines, join, collectInts); //returns list of Integers from string
Integer sumints = fileConv.convertBy(flines, join, collectInts, sum); ////returns list of Integers from string and sums it
用Java做某种可能吗?
编辑:我可以使用重载
答案 0 :(得分:2)
使用泛型时,需要声明所涉及的类型变量。由于使用可变数量的泛型函数(使用varargs)定义链调用的方法将需要可变数量的类型变量,这是不可能的。
在编译时,不可能保证varargs给出的每个函数都使用类型,以便在链接调用时它们是兼容的。
你可以这样做,但不是以类型安全的方式。如果函数的输入/输出类型不匹配,将在运行时产生ClassCastException
。
private static <T, U> U convertBy(T arg, Function... functions) {
Object result = arg;
for (Function f : functions) {
result = f.apply(result);
}
return (U) result;
}
@Test
public void test() {
Function<String, Integer> f1 = s -> s.length();
Function<Integer, Double> f2 = i -> i*2.0;
Double d = convertBy("test", f1, f2);
assertThat(d).isEqualTo(8.0);
}
但是,您可以手动定义该方法的变体,通过重载来完成链接:
private static <T, U> U convertBy(T arg, Function<T, U> func1) {
return func1.apply(arg);
}
private static <T, U, V> V convertBy(T arg, Function<T, U> func1, Function<U, V> func2) {
return func2.apply(func1.apply(arg));
}
private static <T, U, V, X> X convertBy(T arg, Function<T, U> func1, Function<U, V> func2, Function<V, X> func3) {
return func3.apply(func2.apply(func1.apply(arg)));
}