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

在Java中从多维数组获取未知数量的维度,java,arrays,multidimensional-array,dimensions,Java,Arrays,Multidimensional Array,Dimensions,在Java中,是否可以找到具有“先验”未知维数的数组的维数?也就是说,如果不知道多维矩阵的维数,如果可能的话,如何检索它?假设您的矩阵称为m: 您可以通过运行 m.length; 在Java中,多维数组实际上是数组的数组。行数是可变的。假设i是介于0和m.length-1之间的整数,则可以执行以下操作: m[i].length; 获取行中的元素数。我建议您使用只有一个维度的数组来管理此问题。假设有N个尺寸的尺寸: 然后,您可以将阵列的大小定义为: int size = S_0*S_1

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

假设您的矩阵称为m:

您可以通过运行

m.length;
在Java中,多维数组实际上是数组的数组。行数是可变的。假设i是介于0和
m.length-1之间的整数,则可以执行以下操作:

m[i].length;

获取行中的元素数。

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

然后,您可以将阵列的大小定义为:

   int size = S_0*S_1*...*S_N-1;
然后您将对其进行初始化,例如对整数数组进行初始化:

int[] array = new int[size];
然后,要引用数组的一项(读取或写入),您有N个索引(因为有N个维度):

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

基本上,这个公式“跳过”了之前尺寸的正确数量,并指向了正确的位置。这个公式可以简单地用如下方法实现

int read(int[] array, int[] indexes);
void write(int[] array, int[] indexes, int values);
为了保持代码可读性。 您还可以使用泛型类型实现此技术,因此这些方法可能适用于任何类型

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

我不确定我是否正确理解了你想要实现的目标。若你们只想知道数组中有多少元素,阿努比亚的答案是正确的。但我的理解是,你们需要计算给定的一般数组的维数

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);
    }
}
公共类测试{
公共静态int getNumberOfDimensions(类类型){
if(type.getComponentType()==null){
返回0;
}否则{
返回getNumberOfDimensions(type.getComponentType())+1;
}
}
公共静态void main(字符串[]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);
}
}
如果这不是你想要的,我有一个提示:长度和维度之间有区别


更新:我认为这与我们被问到的问题完全无关,但尼古拉在评论中问我:


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

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

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());
    }
}
import java.lang.reflect.Array;
公开课考试{
公共静态类getArrayType(类componentType,int维度)引发ClassNotFoundException{
如果(维度==0){
返回组件类型;
}
字符串rawName=componentType.getName();
开关(rawName){
大小写“byte”:rawName=“B”;中断;
案例“char”:rawName=“C”;中断;
案例“double”:rawName=“D”;中断;
案例“float”:rawName=“F”;中断;
案例“int”:rawName=“I”;中断;
案例“long”:rawName=“J”;中断;
案例“short”:rawName=“S”中断;
大小写“boolean”:rawName=“Z”;break;
违约:
rawName=“L”+rawName+”;”;
打破
}
对于(int i=0;i

诀窍是使用给定的组件类型为N维数组构造一个类。如果我们知道类名是如何存储在最低级别上的,我们就可以这样做。代码的其余部分只是一个简单的、不有趣的递归。

只需通过直接查看初始化的代码或调用其类来查看其动态类型并检查其反映的属性。

这里的首要问题是,你不能一开始就说一些大意如下的话:

int getNumDimensions(int[] array) { ... }
因为如果数组实际上是一个
int[]][]
int[][]][]
等,这将失败。但是Java中的所有数组都是
对象
子类,因此这可以用于任意数量的维度:

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++;
    }
}

你的意思是如何区分
int[]
int[][]
?如果你不知道它的类型,你是如何接收这个数组的?简单地说就是
Object
?对!你可以将它作为一个对象或一些可变的用户输入来接收。情况是,维度的真实数量