如何在java中创建任意深度的嵌套数组?

我正在尝试创建一个数组数组等数组…,除了我不知道它需要多少嵌套级别,直到运行时。

根据输入,我可能需要int[]int[][]int[][][][][][]或其他任何东西。 (对于上下文,我正在尝试为胞自动机构建一个N维网格 ,其中N作为参数传递。)

我没有任何代码,因为我不知道如何去做; 我怀疑只使用数组是不可能的。 任何帮助或替代解决方案,将不胜感激。

您可以使用Object []执行此操作,将其成员限制为Object []或int []。

例如,这是一个数组在一个部分中有三个深度,在另一个部分中有两个深度:

  Object[] myarray = new Object[] { new Object[] { new int[] { 1, 2 }, new int[] { 3, 4 }}, new int[] { 5, 6 } }; 

创建它之后,您可能想要访问成员。 在您的情况下,您知道前面的深度N,因此您知道期望Object []的深度以及期望int []的深度。

但是,如果您不知道深度,则可以使用reflection来确定成员是另一个Object []级别还是叶子int []。

  if ( myarray[0] instanceof Object[] ) { System.out.println("This should print true."); } 

编辑:

这是一个草图[目前为止未经测试,对不起]一个方法,在给定索引数组的情况下访问已知深度数组的成员。 m_root成员可以是Object []或int []。 (您可以进一步放松以支持标量。)

  public class Grid { private int m_depth; private Object m_root; ... public int get( int ... indices ) { assert( indices.length == m_depth ); Object level = m_root; for ( int i = 0; i + 1 < m_depth; ++i ) { level = ((Object[]) level)[ indices[i] ]; } int[] row = (int[]) level; return row[ indices[m_depth - 1] ]; } } 

这应该可以使用Object[]实现,因为数组是对象:

 int[] arr = {1,2,3}; int[] arr2 = {1,2,3}; int[] arr3 = {1,2,3}; int[] arr4 = {1,2,3}; Object[] arr5 = {arr, arr2}; // basically an int[][] Object[] arr6 = {arr3, arr4}; // basically an int[][] Object[] arr7 = {arr5, arr6}; // basically an int[][][] // etc. 

请注意,一个数组不必包含相同维度的数组:

 Object[] arr7 = {arr5, arr}; 

为了防止这种情况(并允许更容易访问数据),我建议编写一个具有Object成员的类(它将是你的int[]Object[] )和一个深度变量以及一些很好的函数来提供访问权限到你想要的。

ArrayList也可以工作:

 ArrayList array = new ArrayList(); array.add(new ArrayList()); array.add(new ArrayList()); ((ArrayList)array.get(0)).add(new ArrayList()); // etc. 

随着嵌套数组的N增加越来越有利,特别是当你有网格结构时。 使用这种方法,N的内存使用量呈指数增长,代码变得复杂。

如果您的网格是稀疏填充的(很多具有相同值的单元格),您可以使用一组Cell对象,其中每个对象都包含坐标向量和单元格的整数值。 假设不在集合中的每个单元格都具有默认值,这是您最常用的值。

为了更快地访问,您可以使用例如kd树( https://en.wikipedia.org/wiki/K-d_tree ),但这取决于您的实际用例。

@Andy Thomas解释了如何使用Object[]来实现更高级别的多维数组。 不幸的是,这意味着类型不正确以允许索引,或者实际上允许在没有类型转换的情况下访问元素。

你不能这样做:

  Object[] array = ... int i = array[1][2][3][4]; 

要获取允许您执行上述操作的类型,您需要创建一个实际类型为(例如) int[][][][]

但另一方面是,对N维数组使用这种索引方式并不实际,其中N是一个变量。 您不能编写Java源代码来执行此操作,除非您将绑定放在N(即最多5)并单独处理不同的情况。 这很快变得无法管理。

您可以使用Javareflection,因为数组是对象。

  public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException { Class intClass = int.class; Class oneDimensionalArrayClass = Class.forName("[I"); Object oneDimensionalIntArray1 = Array.newInstance(intClass, 1); Array.set(oneDimensionalIntArray1, 0, 1); Object oneDimensionalIntArray2 = Array.newInstance(intClass, 1); Array.set(oneDimensionalIntArray2, 0, 2); Object oneDimensionalIntArray3 = Array.newInstance(intClass, 1); Array.set(oneDimensionalIntArray3, 0, 3); Object twoDimensionalIntArray = Array.newInstance(oneDimensionalArrayClass, 3); Array.set(twoDimensionalIntArray, 0, oneDimensionalIntArray1); Array.set(twoDimensionalIntArray, 1, oneDimensionalIntArray2); Array.set(twoDimensionalIntArray, 2, oneDimensionalIntArray1); System.out.println(Array.get(Array.get(twoDimensionalIntArray, 1), 0)); } 

具有静态方法的类Array提供对项的访问,同时您可以使用前导“[”的数量指定数组的维度。

多维数组的整个构造只是编译器在一大块内存上为你做了一些工作(好吧,因为有人在java中注释这是多块内存)。 处理您遇到的问题的一种方法是在运行时使用嵌套的arraylists。 另一种(更高性能)的方法是只分配您需要的大小的一维数组并自己进行索引。 然后,您可以在传递所有详细信息(如数组取消引用)的方法中隐藏索引代码。

 private int[] doAllocate(int[] dimensions) { int totalElements = dimensions[0]; for (int i=1; i< dimensions.length; i++) { totalElements *= dimensions[i]; } int bigOne = new int[totalElements]; return bigOne; } private int deReference(int[] dimensions, int[] indicies, int[] bigOne) { int index = 0; // Not sure if this is only valid when the dimensions are all the same. for (int i=0; i 

上面写的字段是由编译器检查并创建的。 如果您想在运行时期间使用动态数据结构,则可以创建自己的数据结构。 搜索Composite Pattern 。 一个小片段应该告诉你它是如何工作的:

 interface IGrid { void insert(IGrid subgrid); void insert(int[] values); } class Grid implements IGrid { private IGrid subgrid; void insert(IGrid subgrid) {this.subgrid = subgrid;} void insert(int[] values) {/* Do nothing */} } class SubGrid implements IGrid { private int[] values; void insert(IGrid subgrid) {/* Do nothing */} void insert(int[] values) {this.values = values;} } 

你可以简单地为int[]创建一个Subgrid ,或者为int[][]创建一个Subgrid Grid 。 这只是一个基本的解决方案,你必须创建一些代码来处理你的自动机的级别和值。 我会这样做。 希望它会有所帮助:)并期待更多的解决方案^^