任意维数组作为方法参数

时间:2014-08-13 12:16:44

标签: java arrays methods

我有一个简单的转换器方法,用于从booleanint的数组:

public static int[] convert1dToInt (boolean[] x) {

    int la = x.length;
    int[] y = new int[la];

    for (int a = 0; a < la; a++) {
        if (x[a]) {
            y[a] = 1;
        } else {
            y[a] = 0;
        }
    }

    return y;
}

现在我对二维数组有相同的方法:

public static int[][] convert2dToInt (boolean[][] x) {

    int la = x.length;
    int lb = x[0].length;
    int[][] y = new int[la][lb];

    for (int a = 0; a < la; a++) {
        for (int b = 0; b < lb; b++) {
            if (x[a][b]) {
                y[a][b] = 1;
            } else {
                y[a][b] = 0;
            }
        }
    }

    return y;
}

如何在不编写所有方法的情况下,将这些方法推广到任意维度的数组?

3 个答案:

答案 0 :(得分:3)

这是可能的,但反射和递归都是不可避免的:

import java.lang.reflect.Array;

public class ArrayTransfer {

    private static int getArrayDimension(Object array) {
        Class<?> clazz = array.getClass();
        int dimension = 0;
        while (clazz.isArray()) {
            clazz = clazz.getComponentType();
            dimension += 1;
        }

        if (clazz != boolean.class) {
            throw new IllegalArgumentException("Base array type not boolean");
        }

        return dimension;
    }

    // Transfers a boolean array of the specified dimension into an int
    // array of the same dimension.
    private static Object transferToIntArray(Object booleanArray, int dimension) {
        if (booleanArray == null) {
            return null;
        }

        // Determine the component type of the new array.
        Class<?> componentType;
        if (dimension == 1) {
            componentType = int.class;
        } else {
            // We have a multidimensional array; the dimension of the component
            // type is one less than the overall dimension.  Creating the class
            // of an array of an unknown dimension is slightly tricky: we do
            // this by creating a 0 x 0 x ... x 0 array (with dimension - 1
            // zeros) and then getting the class of this array.  Handily for us,
            // int arrays are initialised to all zero, so we can create one and
            // use it straight away.
            int[] allZeroDimensions = new int[dimension - 1];
            componentType = Array.newInstance(int.class, allZeroDimensions).getClass();
        }

        // Create the new array.
        int length = Array.getLength(booleanArray);
        Object newArray = Array.newInstance(componentType, length);

        // Transfer the elements, recursively if necessary.
        for (int i = 0; i < length; ++i) {
            if (dimension == 1) {
                Boolean value = (Boolean)Array.get(booleanArray, i);
                Array.set(newArray, i, (value.booleanValue()) ? 1 : 0);
            }
            else {
                Object oldChildArray = Array.get(booleanArray, i);
                Object newChildArray = transferToIntArray(oldChildArray, dimension - 1);
                Array.set(newArray, i, newChildArray);
            }
        }

        return newArray;
    }

    // Transfers a boolean array of some dimension into an int
    // array of the same dimension.
    public static Object transferToIntArray(Object booleanArray) {
        if (booleanArray == null) {
            return null;
        }

        int dimension = getArrayDimension(booleanArray);
        return transferToIntArray(booleanArray, dimension);
    }
}

这应该适用于任意数量的维度,最多255个 - 我用5进行了快速测试,它似乎有效。它也适用于'锯齿'数组,以及null s。

要使用它,请使用ArrayTransfer.transferToIntArray(...)数组调用boolean,它将返回相应的int数组。您当然需要将此方法的返回值强制转换为相关的int数组类型。

当然有改善这个的余地。特别是,如果保留各种数组类的某些缓存会更好,而不是仅仅为了获得它们的类而实例化空数组。

答案 1 :(得分:1)

这将是您的第一个方法:

    public static int[] convert1dToInt (boolean[] x) {

        //int la = x.length; is useless since you are accessing an object member and not a method

     int[] y = new int[x.length];

        for (int a = 0; a < x.length; a++) {
          y[a] = x[a] ? 1 :0;
    }
    return y;
}

只需重复使用您的代码 - 我没有太多时间,因为这是我的午休时间所以我不知道是否一切都正确但方式应该适合:

public static int[][] convert2dToInt (boolean[][] x)  {

         int[][] y = new int[x.length][];

            for (int a = 0; a < x.length; a++) {
              y[a] = convert1dToInt (x[a]) ;
        }
        return y;
    }

好的,这个解决方案不是问题的答案,因为我没有准确地读到所询问的内容。对不起。据我所知,只要您使用原始数据类型,就不可能使用通用方法。这是因为您不能将int []添加为int []的成员。因此,您应该使用Object [],Boolean []和Integer [],但我不知道您希望如何使用它。我不认为编写这样的方法是明智的,因为当你能够转换这样的数据结构时,你希望如何访问目标。由于您不知道阵列将具有多少维度,因此您无法编写通用方法来访问成员。我会尝试为此编写解决方案,因为我想知道我是否找到了其他可能的解决方案。我是对的,问题是,如果可能而不是合理的话?

如果您告诉我们您希望使用此代码的用例,我认为我们可以找到最佳解决方案。正如我所说,当我稍后有更多时间时,我会尝试寻找另一种解决方案。

答案 2 :(得分:1)

您可以对传递的参数的类型使用条件递归,并使用convert1dToInt作为维度1,然后在一个对象中收集结果,在给定的上下文中,您将被强制传递一个类型Object的对象然后返回一个对象,然后你投了它,这里有一个小代码,它提供了递归函数的想法,它只打印了数组中元素的值:

public static void convertDimN(Object o) {

    if (o.getClass().isArray() && Array.get(o, 0).getClass().isArray()) {
        // is o a two dimentional array
     for (int i = 0; i < Array.getLength(o); i++) {
            convertDimN(Array.get(o, i));
        }
    } else
        for (int i = 0; i < Array.getLength(o); i++) {
            System.out.println(Array.get(o, i));
        }
}