在运行时设置数组的等级

时间:2010-01-15 17:52:24

标签: java arrays multidimensional-array

我想知道最简单的方法是实现一个在运行时指定等级的数组。

我正在处理的示例存储了格点的布尔值数组,我希望用户能够选择模型在运行时使用的空间维数。

我查看了Array.newInstance()方法:

dimensionOfSpace = userInputValue;  // this value comes from GUI or whatever
int latticeLength = 5;  // square lattice for simplicity

int[] dimensions = new int[dimensionOfSpace];
for(int i = 0; i < l.length; i++) l[i] = length; 
Object lattice = Array.newInstance(boolean.class, dimensions);

但是以任何方式访问这些值似乎需要非常慢的方法,例如递归使用Array.get,直到返回的值不再是数组,即使用isArray()。

我在这里错过了一个明显的解决方案吗?我希望能够以类似于foo [i] [j] [k]的方式访问这些值。

4 个答案:

答案 0 :(得分:5)

看起来你正在寻找的是某种方式来声明一个数组在运行时有多少维度。我不知道如何使用多维ArrayList或任何多维结构来完成此操作,您必须在编译时指定维度。

我看到的唯一答案是使用包含在类中的简单线性数组,该类将多维坐标转换为基础数组中的位置。这基本上是像C这样的语言如何通过使用一个连续的内存块来存储多维数组。

代码看起来像这样:

import java.util.*;

class MultiArray<T>{
    private int[] dimensions;
    private Object[] array;

    public MultiArray(int ... dimensions){
        this.dimensions=dimensions;
        //Utils.product returns the product of the ints in an array
        array=new Object[Utils.product(dimensions)];
    }

    public void set(T value, int ... coords){
        int pos=computePos(coords); 
        array[pos]=value;
    }

    public T get(int ... coords){
        int pos=computePos(coords);
        return (T)(array[pos]);
    }

    private int computePos(int[] coords){
        int pos=0;
        int factor=1;
        for (int i=0;i<coords.length;i++){
            pos+=factor*coords[i];
            factor*=dimensions[i];
        }
        return pos;
    }
}

class Main{
    public static void main(String args[]){
        MultiArray<Integer> m=new MultiArray<Integer>(new int[]{5,4,3}); 
        Random r=new Random();

        for(int i=0;i<5;i++)
            for(int j=0;j<4;j++)
                for(int k=0;k<3;k++)
                    m.set(r.nextInt(),i,j,k);
        for(int i=0;i<5;i++){
            for(int j=0;j<4;j++){
                for(int k=0;k<3;k++)
                    System.out.print(m.get(i,j,k)+" ");     
                System.out.println("");
            }
            System.out.println("\n");
        }
    }
}

class Utils{
    public static int product(int...a){
        int ret=1;
        for (int x:a) ret*=x;
        return ret;
    } 
}

答案 1 :(得分:3)

结帐Java Collections。它包含一个名为ArrayList的类,它根据需要增大。

一维

List<Boolean> a = new ArrayList<Boolean>();

二维

List<List<Boolean>> b = new List<List<Boolean>>();

三维

List<List<List<Boolean>>> c = new List<List<List<Boolean>>>();

您可以使用c.get(i).get(j).get(k)代替c[i][j][k]访问该项目,就像在3d数组中一样。或者甚至更好,将它包装在您自己的类中,并在那里使用get()方法。所以它变成了:

c.get(i, j, k);

修改

要获得深度为N的多维列表,请删除Boolean类型指示符,然后将列表创建为

List level1 = new ArrayList();
List level2 = new ArrayList();
List level3 = new ArrayList();
level1.add(level2);
level2.add(level3);

依旧......

答案 2 :(得分:3)

我将使用术语“rank”来表示数组中的“维数”。因此,向量具有等级1,矩阵具有等级2,依此类推。你已经接受了一个答案,你自己承认并不是你想要的。这是另一种解决方案:

回想一下,计算机内存基本上是线性的,编译器在为数组提供数据时所做的事实上是将索引表达式转换为线性地址。如果您假设所有数组都在连续的内存中,这是最简单的考虑,并非总是如此。假设你做了一个声明,如ARRAY_OF_TYPE [10] [10] [10],即它有1000个元素。然后,在位置baseAddress + 354 * size_of_element_of_TYPE,位置[3] [5] [4]的元素是(我的数组从1开始索引而不是0 - 在你想要的时候改变后面的和)。

我希望你现在知道我要去哪里......

在运行时,程序会提示输入用户的整数列表。每个整数指定数组的一个维度的大小,整数的数量指定数组的等级。你的程序做了一些乘法,你分配了一个正确长度的向量。好的,你必须编写索引和去索引函数,但这些函数应该相当简单。

et voila 你有一个数组,其排名是在运行时建立的。

答案 3 :(得分:1)

我快速谷歌搜索“{张量”,提出了DJEP,这可能适合您的账单吗?