在java中创建5D或6D数组的最佳方法

时间:2014-09-09 21:50:46

标签: java arrays multidimensional-array

我正在重新设计一个创建了6D数组的代码。这是Cplex线性计算所必需的。

现在,有一些API可以支持cplex中的1D或int变量,因此拥有6维数组并不重要。 只有映射对于从另一个方法检索变量时需要的变量很重要。

有没有办法更换6D阵列。这也有助于简化代码的复杂性。

- >我能以某种方式替换6D数组并将变量存储在1D数组或int变量中。 - >我尝试使用键作为列表的HashMap和值作为整数的值,但最终它花费更多的时间,因为HashMap内部使用数组。

示例代码为:

int [][][][][][] testVariable = new int [2][2][3][5][2][2];
        HashMap<List<Integer>, Integer> mapping = new HashMap<List<Integer>, Integer>();
        int[] arrayAdd = new int[11111];

    for (int a =0; a <= 2; a++) {       
        for (int l = 0; l < 2; l++) {
                for (int y = 0; y < 3; y++) {
                    for (int r = 0; r < 5; r++) {
                        for(int oc=0; oc< 2; oc++){
                            for(int c=0; c< 2; c++){

                                // usual array of 6D

                                testVariable[a][l][y][r][oc][c]=count;

                                // FIRST METHOD ( Takes more time then Array) 

                                LinkedList<Integer> listAdd = new LinkedList<Integer>();
                                listAdd.add(a);
                                listAdd.add(l);
                                listAdd.add(y);
                                listAdd.add(r);
                                listAdd.add(oc);
                                listAdd.add(c);
                                mapping.put(listAdd, count);

                                // second method .. this i am still testing but it doesnt make much sense)

                                arrayAdd[a + l + y + r + oc + c] = count;


                            //  Arrays.fill(arrayAdd, count);
                                //System.out.println("Value of list is  " + listAdd);
                                count ++;

                        }
                    }
                }
            }
       }
  }

3 个答案:

答案 0 :(得分:3)

如果您知道每个尺寸的长度都不会改变,那么您可以使用1D阵列模拟6D阵列。诀窍是将除最后一个索引c之外的所有索引的索引乘以足够高的数字,以便在映射到相同1D索引的不同6D索引集之间不会发生任何冲突。

int[] oneDArray = new int[2*2*3*5*2*2];

用于计算1D指数,使用6个6D指数。在每个特定的6D指数之后乘以所有维度长度的乘积将避免碰撞。

int oneDIndex = 2*3*5*2*2 * a  // last 5 dimensions' lengths
              +   3*5*2*2 * l  // last 4 dimensions' lengths; variable letter l
              +     5*2*2 * y  // last 3 dimensions' lengths
              +       2*2 * r  // last 2 dimensions' lengths
              +         2 * oc // last dimension's length only
              +             c; // no multiplier necessary for last index

最好在这里使用每个尺寸长度的常量,以减少硬编码。

答案 1 :(得分:0)

只是我的意见,但假设我想要一个非稀疏的超矩形,我会使用一维Java数组,并自己做索引算法。

,例如,对于包含3行和5列的2D数组:

final int num_rows = 3;
final int num_cols = 5;

final T[] storage = new T[num_rows * num_cols];

T get(int row, int col) {
    assert(row >= 0);
    assert(row < num_rows);
    assert(col >= 0);
    assert(col < num_cols);
    return storage[row*num_cols + col];
}

你可以想象这将如何推广到两个以上的维度。

提示:我会将num_rows和num_cols替换为一个名为&#39; dimension&#39;的有效不可变数组。维度数组的长度将是呈现给客户端的维度数。存储阵列的长度将是维度数组的所有成员的乘积,依此类推。

答案 2 :(得分:0)

扩展rgettman的答案并证明更一般的方式从6D-> 1D转换,反之亦然。

  1. 将6D数组转换为1D数组:

    int[] sixDArrayToOneDArray(final int[][][][][][] sixDArray) {
    
        int dim1Length = sixDArray.length;
        int dim2Length = sixDArray[0].length;
        int dim3Length = sixDArray[0][0].length;
        int dim4Length = sixDArray[0][0][0].length;
        int dim5Length = sixDArray[0][0][0][0].length;
        int dim6Length = sixDArray[0][0][0][0][0].length;
    
        int[] result = new int[dim1Length * dim2Length * dim3Length * dim4Length * dim5Length * dim6Length];
    
        for (int i1 = 0; i1 < dim1Length; i1++)
            for (int i2 = 0; i2 < dim2Length; i2++)
                for (int i3 = 0; i3 < dim3Length; i3++)
                    for (int i4 = 0; i4 < dim4Length; i4++)
                        for (int i5 = 0; i5 < dim5Length; i5++)
                            for (int i6 = 0; i6 < dim6Length; i6++) {
                                int oneDIndex = i1 * dim2Length * dim3Length * dim4Length * dim5Length * dim6Length
                                              + i2 * dim3Length * dim4Length * dim5Length * dim6Length                                        + i3 * dim4Length * dim5Length * dim6Length
                                              + i4 * dim5Length * dim6Length
                                              + i5 * dim6Length
                                              + i6;
                                result[oneDIndex] = sixDArray[i1][i2][i3][i4][i5][i6];
                            }
    
        return result;
    }
    
  2. 将1D数组转换为6D数组:

    int[][][][][][] oneDArrayToSixDArray(int[] oneDArray, int dim1Length, int dim2Length, int dim3Length, int dim4Length, int dim5Length, int dim6Length) {
    
        if (oneDArray.length != dim1Length * dim2Length * dim3Length * dim4Length * dim5Length * dim6Length) {
            throw new IllegalArgumentException(String.format("One dimension array length [%s] does not match to six dimensions array lengths [%s, %s, %s, %s, %s, %s]", dim1Length, dim2Length, dim3Length, dim4Length, dim5Length, dim6Length));
        }
    
        int[][][][][][] result = new int[dim1Length][dim2Length][dim3Length][dim4Length][dim5Length][dim6Length];
        for (int i = 0; i < oneDArray.length; i++) {
            int i1 =  i / (dim2Length * dim3Length * dim4Length * dim5Length * dim6Length);
            int i2 = (i % (dim2Length * dim3Length * dim4Length * dim5Length * dim6Length)) / (dim3Length * dim4Length * dim5Length * dim6Length);
            int i3 = (i % (dim3Length * dim4Length * dim5Length * dim6Length)) / (dim4Length * dim5Length * dim6Length);
            int i4 = (i % (dim4Length * dim5Length * dim6Length)) / (dim5Length * dim6Length);
            int i5 = (i % (dim5Length * dim6Length)) / dim6Length;
            int i6 =  i % dim6Length;
            result[i1][i2][i3][i4][i5][i6] = oneDArray[i];
        }
    
        return result;
    }