计算一个数组迭代的多个结果

时间:2011-04-06 18:29:30

标签: java functional-programming performance metaprogramming iteration

我想在数组或列表的一次迭代中计算多个函数,但可能希望动态增加函数列表。例如,我可能想要计算最小值和最大值,然后,还需要稍后的平均函数(或任何其他线性复杂度函数)。所以,我可能希望有一个高级规范(使用一些名为addFuncapplyAllFuncs的函数,例如

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中完成(或可以完成)(无需做很多事情来模拟/实现更高级别的功能)。

3 个答案:

答案 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);