我有一个程序,将动态访问不同的方法,每个方法将有不同数量的参数。我需要找到一种方法来排列这些参数的数千种不同排列,我不确定如何动态地循环这些排列。
例如,对于有两个形参的函数,我可以像这样遍历排列:
public static void main(String[] args) {
List<Object[]> params = new ArrayList();
params.add(new Integer[]{1,2,3});
params.add(new Boolean[]{false,true});
runCalculation("function1",params);
}
public void runCalculation(String functionName, List<Object> parameters){
for(Object i : parameters.get(0)){
for(Object j : parameters.get(1)){
//Do reflection function call with (i,j) as parameters
}
}
}
但是如果我有下一个函数,我想运行使用3个参数,这将不再迭代所有的排列。如何使用动态数量的for循环来正确处理包含参数值的数组列表?我认为递归是实现这类东西的唯一方法,但我仍然在努力想出一个正确的解决方案,这将正确地允许每个函数的动态参数,然后为这些参数提供不同的类型。
public void runCalculation(String functionName, List<Object> ... parameters){
for(List<Object> list : parameters)
{
//Do reflection function call with obj as parameter
}
}
被称为varargs,也尝试使用增强的for -它更容易使用并且开销很小
我想你在这里尝试的是反思。您只需要阅读API并使用适当的方法。注意,将需要知道要在哪个类上调用方法名。Java不会为你检查所有类中的所有方法。
public void runCalculation(String functionName, List<Object> parameters)
throws NoSuchMethodException
{
Class<?>[] typeSignature = new Class<?>[ parameters.size() ];
for( int i = 0; i < parameters.size(); i++ ) {
typeSignature[i] = parameters.get( i ).getClass();
}
Class<?> type = this.getClass(); // substitute with desired class
Method m = type.getMethod(functionName, typeSignature);
// do stuff with 'm' here (like invoke it)
}
如果我不理解这个问题,我很抱歉,但是嵌套的for循环呢?
for(int i = 0; i < params.size(); i++)
{
for(int j = 0; j < params.get(i).size(); j++)
{
}
}
这个可行吗?
编辑:我知道你在找什么算法了递归解是:
public static String recursive(List<Object[]> params)
{
String result = "";
if(Params.isEmpty())
return result;
Object[] objects = params.remove(0);
for(Object i : objects)
{
result += i.toString();
List<Object[]> newParams = new ArrayList<>(newParams);
result += recursive(newParams);
}
return result;
}
这是我的解决方案(我不知道数组不实现Iterable
,我现在懒得改变它,因为它是基于交互器):
public static void print(Object a, Object b, Object c) {
System.out.format("%s, %s, %sn", a, b, c);
}
public static void runCalculation(Method m, Object instance, List<Iterable<?>> argList)
throws Exception {
int argc = argList.size(); //ARG Count
int depth = 0;
Stack<Iterator<?>> iteratorStack = new Stack<>();
Object[] args = new Object[argc]; //call with these args
boolean fromTop = true; //to know where we come from
while (depth > -1) {
if (fromTop && depth == argc) {
m.invoke(instance, args);
depth--;
fromTop = false;
} else if(fromTop) {
iteratorStack.push(argList.get(depth).iterator());
fromTop = false;
} else if (iteratorStack.peek().hasNext()) {
args[depth] = iteratorStack.peek().next();
depth++;
fromTop = true;
} else {
iteratorStack.pop();
depth--;
fromTop = false;
}
}
}
public static void main(String[] args) throws Exception {
List<Iterable<?>> list = new ArrayList<>();
list.add(Arrays.asList("one", "two"));
list.add(Arrays.asList(3, 4));
list.add(Arrays.asList(true, false));
Method m = NaryProduct.class.getMethod("print", Object.class, Object.class, Object.class);
runCalculation(m, null, list);
}
输出:one, 3, true
one, 3, false
one, 4, true
one, 4, false
two, 3, true
two, 3, false
two, 4, true
two, 4, false
下面是如何在C中做类似的事情:应该很容易转换到Java。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
runCalculation( char * functionName, char * parameters, int numParams )
{
int size = strlen(parameters); // number of parameters to choose from
int i, j;
int indices[numParams];
for (i=0; i < numParams; ++i)
// initialise indices
indices[i] = i;
while (1) {
// output parameters
for (i=0; i < numParams; ++i)
printf("%c", parameters[indices[i]]);
printf("n");
// now advance j'th parameter
j = numParams - 1;
while(1) {
indices[j]++;
if (indices[j] < size - (numParams-1-j))
// found a combination that 'works'
break;
// can't create a new combination with current j, so try new one
--j;
if (j < 0)
return;
}
// reset everything after indices[j]: they will all be consecutive
for (i=j+1; i < size; ++i)
indices[i] = indices[i-1] + 1;
}
}
main( int argc, char ** argv) {
if (argc != 3) {
printf("need two arguments (string to permute, # of combo elements): byen");
exit(1);
}
runCalculation( "testFunction", argv[1], atoi(argv[2]) );
}
输入"abcdef"和4时的输出:
abcd
abce
abcf
abde
abdf
abef
acde
acdf
acef
adef
bcde
bcdf
bcef
bdef
cdef
将代码保存到您的系统中,编译它,尝试各种测试用例,一旦您确信这是您所需要的,然后向我展示编写此代码的Java方法。只是想让我知道。谢谢你。