如何动态增加2D数组的大小

时间:2013-11-29 17:45:33

标签: java arrays

如果我知道有多少元素,我已经知道如何制作一个固定数组。例如,对于7个元素,我执行类似int array [2] [4]。

的操作

但是如果我在启动时有0个元素(这意味着数组在启动时将为空)并希望在程序运行时增加数组大小,该怎么办?

基本上,如何添加新的行或列?

6 个答案:

答案 0 :(得分:1)

ArrayList文档和Examples。享受!

具体做法是:

ArrayList<Integer> list = new ArrayList<Integer>();
list.add(1); // Add 1 to the list.

答案 1 :(得分:1)

请注意,new int[2][4]int[]的数组; int[]数组中的int[][]数组最初都是相同的长度,但并不要求它们保持相同的长度。可以使用不同的长度重新分配int[][]数组的任何元素int[],而不会影响其他元素。 “行”和“列”的概念是Java数组不支持的更高级别的想法。

使用ArrayList作为其他答案建议不会改变这一点。此外,根据ArrayList的使用方式,由于将int值自动装箱为Integer个对象,最终可能会产生相当大的开销。

如果您想保留数据的矩形形状,我建议您定义一个Matrix类,以保持所有维度的一致性。 (或者,或许更好,将二维数组线性化为一维数组,并使用内部存储的行和列大小进行适当的下标计算。或者,或许最好,使用编写良好的矩阵库,如{{3}或者像JAMA这样的原始集合库。)

编辑这是一个简单的矩阵类的开始,它在内部使用线性存储方案并允许矩阵大小调整。数据存储在Trove中,索引基于0。

public class IntMatrix {
    private int rows;
    private int cols;
    private int[] data;

    /**
     * Allocate a matrix with the indicated initial dimensions.
     * @param cols The column (horizontal or x) dimension for the matrix
     * @param rows The row (vertical or y) dimension for the matrix
     */
    public IntMatrix(int cols, int rows) {
        this.rows = rows;
        this.cols = cols;
        data = new int[cols * rows];
    }

    /**
     * Calculates the index of the indicated row and column for
     * a matrix with the indicated width. This uses row-major ordering
     * of the matrix elements.
     * <p>
     * Note that this is a static method so that it can be used independent
     * of any particular data instance.
     * @param col The column index of the desired element
     * @param row The row index of the desired element
     * @param width The width of the matrix
     */
    private static int getIndex(int col, int row, int width) {
        return row * width + col;
    }

    public int get(int col, int row) {
        return data[getIndex(col, row, cols)];
    }

    public void set(int col, int row, int value) {
        data[getIndex(col, row, cols)] = value;
    }

    /**
     * Resizes the matrix. The values in the current matrix are placed
     * at the top-left corner of the new matrix. In each dimension, if
     * the new size is smaller than the current size, the data are
     * truncated; if the new size is larger, the remainder of the values
     * are set to 0.
     * @param cols The new column (horizontal) dimension for the matrix
     * @param rows The new row (vertical) dimension for the matrix
     */
    public void resize(int cols, int rows) {
        int [] newData = new int[cols * rows];
        int colsToCopy = Math.min(cols, this.cols);
        int rowsToCopy = Math.min(rows, this.rows);
        for (int i = 0; i < rowsToCopy; ++i) {
            int oldRowStart = getIndex(0, i, this.cols);
            int newRowStart = getIndex(0, i, cols);
            System.arraycopy(data, oldRowStart, newData, newRowStart,
                colsToCopy
            );
        }
        data = newData;
    }

    . . .
}

答案 2 :(得分:1)

这是为什么无法调整大小。无论您有1维还是20维,数组的每个维都被分配为某个地方的连续数据行,而任何此类序列之后的存储空间对于其他变量和数据来说都是合理的游戏。例如,ary = new int [4]可能会在内存中表示如下:

| ary[0] | ary[1] | ary[2] | ary[3] | otherNearbyData1 | otherData2 | ...

由于在数组数据之后可能会有其他变量,因此必须分配一个具有所需大小的新数组,并将旧数组中的所有元素复制到新数组中。一种策略是每次达到100%容量时将分配大小加倍,以获得恒定的摊销时间复杂度。这或多或少是ArrayList所做的,但是正如Peter Lawrey所指出的那样浪费了大量的空间。

根据您的需要,一种替代方案可能是LinkedList,其中每个数据元素都是单独分配的,并包含指向下一个/上一个元素的指针。尽管完全紧凑(没有浪费空间)并且能够增长到任何尺寸,但链接列表有两个主要缺点:

  • 无随机访问(您只能从一个元素遍历到下一个/上一个元素)。
  • 非常低效的时间 - 跳过地址空间只是为了到达每个下一个元素,完全可以消除CPU缓存中的风。

编辑:第二个想法......即使2D链接列表是可能的,您需要多个维度的事实可能意味着顺序遍历对您来说还不够。我的坏。

答案 3 :(得分:0)

创建一个更大的新数组,复制现有元素并添加要添加的元素。您可以使用像ArrayList这样的东西,但这很昂贵,并且将使用大约4倍的内存。如果您不想自己调整阵列大小,我会考虑使用TDoubleArrayList

答案 4 :(得分:0)

可以动态创建Java数组,但不能动态扩展。您可能希望将VectorArrayList视为其他建议。

但是,请记住,在您的示例中,您创建的矩阵略有不同。

答案 5 :(得分:0)

当然你可以使用Collections(例如ArrayList),但是如果你想使用2D Matrix,你可以“动态”创建不同大小的行。例如,以下示例创建“三角形”矩阵:

int[][] matrix = new int[3][];
int count = 0;
for (int i = 0; i < 3; i++) {
    matrix[i] = new int[i];
    for (int j = 0; j < i; j++) {
        matrix[i][j] = ++count;
    }
}