从Java中的多维数组中获取未知数量的维度

时间:2014-04-22 21:49:20

标签: java arrays multidimensional-array dimensions

在Java中是否有可能找到具有'先验'未知维数的数组的维数?也就是说,如果一个人不知道多维矩阵的维数,如果可能的话,如何检索它呢?

5 个答案:

答案 0 :(得分:9)

  

有没有人知道在Java中是否可以获得具有'先验'未知维数的数组的维数?也就是说,如果一个人不知道多维矩阵的维数,如果可能的话,如何检索它呢?

我不确定我是否理解你想要完成的事情。如果您只想知道数组中有多少元素,Anubian的答案是正确的。但我所理解的是,您想要计算给定通用数组的维数。

public class Test {
    public static int getNumberOfDimensions(Class<?> type) {
        if (type.getComponentType() == null) {
            return 0;
        } else {
            return getNumberOfDimensions(type.getComponentType()) + 1;
        }
    }

    public static void main(String[] args) {
        System.out.println(getNumberOfDimensions(int[][][].class)   == 3);
        System.out.println(getNumberOfDimensions(int[][].class)     == 2);
        System.out.println(getNumberOfDimensions(int[][][][].class) == 4);
        System.out.println(getNumberOfDimensions(int.class)         == 0);
    }
}

如果那不是你想要的,我会有一个提示:长度维度之间存在差异。


更新:我认为这与我们的要求完全无关,但Nicola在评论中问我:

  

这很有效,但是如果在运行时定义了维度数量(例如用户必须输入所需的维度)呢?如何定义和初始化数组?

解决方案在于一些基于光反射的黑客行为:

import java.lang.reflect.Array;

public class Test {
    public static Class<?> getArrayType(Class<?> componentType, int dimensions) throws ClassNotFoundException {
        if (dimensions == 0) {
            return componentType;
        }

        String rawName = componentType.getName();
        switch (rawName) {
            case "byte":    rawName = "B"; break;
            case "char":    rawName = "C"; break;
            case "double":  rawName = "D"; break;
            case "float":   rawName = "F"; break;
            case "int":     rawName = "I"; break;
            case "long":    rawName = "J"; break;
            case "short":   rawName = "S"; break;
            case "boolean": rawName = "Z"; break;
            default:
                rawName = "L" + rawName + ";";
                break;
        }

        for (int i = 0; i < dimensions; i++) {
            rawName = "[" + rawName;
        }

        return Class.forName(rawName);
    }

    public static Object createArray(Class<?> componentType, int dimensions, int length) throws NegativeArraySizeException, ClassNotFoundException {
        if (dimensions == 0) {
            return null;
        }

        Object array = Array.newInstance(getArrayType(componentType, dimensions - 1), length);

        for (int i = 0; i < length; i++) {
            Array.set(array, i, createArray(componentType, dimensions - 1, length));
        }

        return array;
    }

    public static void main(String[] args) throws ClassNotFoundException {
        Object object = createArray(Integer.class, 3, 10);
        System.out.println(object.getClass());
    }
}

技巧是使用给定的组件类型为N维数组构造一个Class。如果我们知道类名如何存储在最低级别,我们就可以做到这一点。其余的代码只是一个简单的无趣递归。

答案 1 :(得分:1)

假设您的矩阵名为m:

您可以通过运行

获取列数
m.length;

使用Java,多维数组实际上是数组的数组。行数是可变的。假设我是0和m.length-1之间的整数,你可以这样做:

m[i].length;

获取行中元素的数量。

答案 2 :(得分:1)

这里最初的问题是你不能首先说出以下内容:

int getNumDimensions(int[] array) { ... }

因为如果theArray实际上是int[][]int[][][]等,这会失败。但是Java中的所有数组都是Object子类,所以这可以适用于任何数字尺寸:

int getNumDimensions(Object array) {zz
    if (array instanceof Object[]) {
        // array has at least 2 dimensions (e.g. int[][])
        return getNumDimensions(((Object[]) array)[0]) + 1;
    }
    if (array.getClass().isArray()) {
        // array is, by process of elimination, one-dimensional
        return 1;
    }
    return 0;
}

编辑:我已经尝试过针对那些疯狂的百万维数组的非递归解决方案了!

int getNumDimensions(Object array) {
    Object tmp = array;
    int nDimensions = 0;
    while (True) {
        if (array instanceof Object[]) {
            // tmp has at least 2 dimensions (e.g. int[][])
            tmp = ((Object[]) array)[0];
        }
        else if (tmp.getClass().isArray()) {
            // tmp is, by process of elimination, one-dimensional
            return nDimensions + 1;
        }
        nDimensions++;
    }
}

答案 3 :(得分:0)

我建议您使用仅包含一个维度的数组来管理此问题。假设有N个尺寸的尺寸:

size of the N dimensions

然后您可以将数组的大小定义为:

   int size = S_0*S_1*...*S_N-1;

然后你将初始化它,例如对于一个整数数组:

int[] array = new int[size];

然后要引用数组的项目(读取或写入),你有N个索引(由于N个维度):

indexes to refer the array

你现在需要的是一种转换这N个索引的方法,在一个可以用作一维数组中的索引的值中,通用公式为:

how transform the N indexes in one index for the one-dimensional array

这个公式基本上'跳过'正确数量的先前尺寸并指向正确的位置。这个公式可以简单地用像

这样的方法实现
int read(int[] array, int[] indexes);
void write(int[] array, int[] indexes, int values);

以保持代码可读。 您也可以使用泛型类型实现此技术,因此这些方法可能适用于任何类型。

答案 4 :(得分:0)

只需直接查看初始化的代码或调用其类并检查其反射属性,即可查看其动态类型。