我想在数组或列表的一次迭代中计算多个函数,但可能希望动态增加函数列表。例如,我可能想要计算最小值和最大值,然后,还需要稍后的平均函数(或任何其他线性复杂度函数)。所以,我可能希望有一个高级规范(使用一些名为addFunc
和applyAllFuncs
的函数,例如
funcs = emptyFunctionList; # no functions in funcs "list" yet
funcs = addFunc (min, funcs); # add minimum function
funcs1 = addFunc (max, funcs); # add maximum function
answers1 = applyAllFuncs (funcs1, myArray);
funcs2 = addFunc (avg, funcs); # add average function
answers2 = applyAllFuncs (funcs2, myArray);
我可以通过从这些函数创建一个传递给foldl
的“超级函数”,在函数式语言中很容易地做到这一点,并且元编程可能是一种在Haskell / C ++中更有效地执行此操作的机制。 ,但想知道是否有一种高效且不太复杂的方式,通常在标准Java中完成(或可以完成)(无需做很多事情来模拟/实现更高级别的功能)。
答案 0 :(得分:1)
这是完整的工作Java代码,相当于您在帖子中提供的功能伪代码:
import java.util.*;
interface Function1<A, B> {
public B apply(final A a);
}
class Main {
public static <A, B> List<Function1<A, B>> addFunc(final Function1<A, B> f, final List<Function1<A, B>> fs) {
final List<Function1<A, B>> gs = new ArrayList<Function1<A, B>>();
gs.addAll(fs);
gs.add(f);
return gs;
}
public static <A, B> List<B> applyAllFuncs(final List<Function1<List<A>, B>> fs, final List<A> as) {
final List<B> bs = new ArrayList<B>();
for(final Function1<List<A>, B> f : fs) {
bs.add(f.apply(as));
}
return bs;
}
public static Function1<List<Double>, Double> min = new Function1<List<Double>, Double>() {
public Double apply(final List<Double> xs) {
double mx = xs.get(0);
for(final Double x : xs) {
if(x < mx) {
mx = x;
}
}
return mx;
}
};
public static Function1<List<Double>, Double> avg = new Function1<List<Double>, Double>() {
public Double apply(final List<Double> xs) {
double sum = 0;
for(final Double x : xs) {
sum += x;
}
return sum / xs.size();
}
};
public static Function1<List<Double>, Double> max = new Function1<List<Double>, Double>() {
public Double apply(final List<Double> xs) {
double mx = xs.get(0);
for(final Double x : xs) {
if(x > mx) {
mx = x;
}
}
return mx;
}
};
public static void main(final String[] args) {
final List<Double> myArray = Arrays.asList(3.0, 8, 1, 2, 9);
List<Function1<List<Double>, Double>> funcs = new ArrayList<Function1<List<Double>, Double>>();
funcs = addFunc(min, funcs);
final List<Function1<List<Double>, Double>> funcs1 = addFunc(max, funcs);
final List<Double> answers = applyAllFuncs(funcs1, myArray);
final List<Function1<List<Double>, Double>> funcs2 = addFunc(avg, funcs);
final List<Double> answers2 = applyAllFuncs(funcs2, myArray);
System.out.println(answers + "\n" + answers2);
}
}
如果您使用已有的Java函数编程库(如Functional Java或GridGain提供的函数编程库),则可以避免大部分样板文件。
由于JVM从未打算用于此类内容,因此不会对此进行优化。 Scala是JVM上的一种函数式语言,它使用与上面相同的方法来实现lambda和更高阶函数,并提供与Java相当的性能。我仍然建议您分析代码并确定它是否满足您特定用例的性能要求。
答案 1 :(得分:0)
创建自己的折叠:
有一个方法可以获取列表和列表中要运行的函数列表
要在列表上运行的函数列表可能只是ArrayList<XFunction>
,其中XFunction
是您定义的具有方法的类(比如run(...)
),您可以创建它的匿名实现对于每个功能。
前:
list.add(new XFunction(){
run(ArrayList<int> numbers){
return numbers.size();
}
}
当然,这不是解决任何问题的功能,但你明白了
答案 2 :(得分:0)
您可以使用某种策略模式:
public interface Function{
public void Compute();
}
public Function1 implements Function{
public void Compute(){
System.out.println("This is Function1");
}
}
public Function2 implements Function{
public void Compute(){
System.out.println("This is Function2");
}
}
之后声明一个Function:
的容器ArrayList<Function> functions = new ArrayList<Function>();
functions.add(new Function1());
functions.add(new Function2());
ArrayList<Object> someData = new ArrayList<Object>();
Something.execute(someData,functions);