是否可以在Java中动态构建多维数组?

假设我们有 Java 代码:

Object arr = Array.newInstance(Array.class, 5);

会这样吗?作为进一步的注意,如果我们要尝试这样的事情会怎么样:

Object arr1 = Array.newInstance(Array.class, 2);
Object arr2 = Array.newInstance(String.class, 4);
Object arr3 = Array.newInstance(String.class, 4);
Array.set(arr1, 0, arr2);
Array.set(arr1, 1, arr3);

那么 arr1 将是一个 2D 数组,等效于:

String[2][4] arr1;

怎么样:如果我们在运行时之前不知道这个数组的尺寸怎么办?

编辑:如果这有帮助(我相信它会...),我们正试图从形式的字符串中解析未知维度的数组

[value1, value2, ...]

[ [value11, value12, ...] [value21, value22, ...] ...]

等等

Edit2:万一像我这样愚蠢的人尝试这个垃圾,这里有一个至少编译和运行的版本。逻辑是否合理完全是另一个问题......

Object arr1 = Array.newInstance(Object.class, x);
Object arr11 = Array.newInstance(Object.class, y);
Object arr12 = Array.newInstance(Object.class, y);
...
Object arr1x = Array.newInstance(Object.class, y);
Array.set(arr1, 0, arr11);
Array.set(arr1, 1, arr12);
...
Array.set(arr1, x-1, arr1x);

等等。它只需要是一个巨大的嵌套对象数组


答案 1

实际上,在java中是可能的。(我必须说,我有点惊讶。

免责声明;我从来不想在其他地方看到这段代码,除了作为这个问题的答案。我强烈建议您使用 s。List

import java.lang.reflect.Array;
import java.util.*;

public class Test {

    public static int[] tail(int[] arr) {
        return Arrays.copyOfRange(arr, 1, arr.length);
    }

    public static void setValue(Object array, String value, int... indecies) {
        if (indecies.length == 1)
            ((String[]) array)[indecies[0]] = value;
        else
            setValue(Array.get(array, indecies[0]), value, tail(indecies));
    }

    public static void fillWithSomeValues(Object array, String v, int... sizes) {
        for (int i = 0; i < sizes[0]; i++)
            if (sizes.length == 1)
                ((String[]) array)[i] = v + i;
            else
                fillWithSomeValues(Array.get(array, i), v + i, tail(sizes));
    }

    public static void main(String[] args) {

        // Randomly choose number of dimensions (1, 2 or 3) at runtime.
        Random r = new Random();
        int dims = 1 + r.nextInt(3);

        // Randomly choose array lengths (1, 2 or 3) at runtime.
        int[] sizes = new int[dims];
        for (int i = 0; i < sizes.length; i++)
            sizes[i] = 1 + r.nextInt(3);

        // Create array
        System.out.println("Creating array with dimensions / sizes: " +
                Arrays.toString(sizes).replaceAll(", ", "]["));
        Object multiDimArray = Array.newInstance(String.class, sizes);

        // Fill with some 
        fillWithSomeValues(multiDimArray, "pos ", sizes);

        System.out.println(Arrays.deepToString((Object[]) multiDimArray));


    }
}

输出示例:

Creating array with dimensions / sizes: [2][3][2]
[[[pos 000, pos 001], [pos 010, pos 011], [pos 020, pos 021]],
 [[pos 100, pos 101], [pos 110, pos 111], [pos 120, pos 121]]]

答案 2

数组在java中是类型安全的 - 适用于简单数组和“多维”数组 - 即数组的数组。

如果嵌套深度在运行时是可变的,那么您可以做的最好的方法是使用与已知的最小嵌套深度(大概为 1)相对应的数组。此数组中的元素要么是简单元素,要么是如果需要进一步嵌套,则是另一个数组。Object[] 数组将允许您执行此操作,因为嵌套数组本身也被视为对象,因此适合类型系统。

如果嵌套是完全正则的,那么你可以抢占这种规律性,创建一个合适的多维数组,使用,如果嵌套是不规则的,你会最好使用嵌套列表,它允许“锯齿状”结构和动态大小调整。您可以在泛型的 expence 处具有锯齿状结构。如果结构是锯齿状的,则不能使用泛型,因为某些元素可能是简单项,而其他元素可能是进一步的嵌套列表。Array.newInstance(String.class, dimension1, dimension2, ...)