[英]How to dynamically increase size of a 2D array
如果我知道有多少个元素,我已经知道如何制作固定数组。 例如,对于7个元素,我会执行类似int array [2] [4]的操作。
但是,如果我在开始时有0个元素(这意味着数组在开始时将为空)并想在程序运行时增加数组大小怎么办?
基本上,如何添加新的行或列?
注意new int[2][4]
是int[]
的数组; int[]
数组中的int[][]
数组最初都具有相同的长度,但是不要求它们保持相同的长度。 可以将int[][]
数组的任何元素重新分配为具有不同长度的int[]
,而完全不影响其他元素。 “行”和“列”的概念是更高级别的概念,Java数组不支持。
使用ArrayList
作为其他答案表明不会改变这一点。 此外,由于将int
值自动装箱为Integer
对象,根据使用ArrayList
,可能会产生相当大的开销。
如果要保留数据的矩形形状,建议您定义一个Matrix
类,使所有维保持一致。 (或者,也许更好,将二维数组线性化为一维数组,并使用内部存储的行和列大小进行适当的下标计算。或者,也许最好,使用编写良好的矩阵库(例如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;
}
. . .
}
这就是为什么无法调整大小的原因 。 无论是1维还是20维,数组的每个维都作为连续的数据行分配在某处,任何此类序列之后的存储空间都是公平的,可供其他变量和数据使用。 例如,ary = new int [4]可以这样表示在内存中:
| ary[0] | ary[1] | ary[2] | ary[3] | otherNearbyData1 | otherData2 | ...
由于数组数据之后可能还会有其他变量,因此您必须分配一个具有所需大小的新数组,并将所有元素从旧数组复制到新数组。 一种策略是,每次达到100%的容量时,分配大小就会增加一倍,以获取固定的摊销时间复杂度。 这或多或少是ArrayList所做的,但是正如Peter Lawrey指出的那样,这浪费了大量的空间。
根据您的需要的一种替代方法可能是LinkedList,其中每个数据元素都被单独分配,并包含指向下一个/上一个元素的指针。 尽管链表非常紧凑(没有浪费的空间)并且可以增长到任意大小,但是它具有两个主要缺点:
编辑:再三考虑...即使2D链表是可能的,但您需要多个维度的事实可能意味着顺序遍历对您来说还不够。 我的错。
创建一个更大的新数组,复制现有元素并添加要添加的元素。 您可以使用类似ArrayList的方法,但这很昂贵,并且将使用大约4倍的内存。 如果您不想自己调整数组的大小,我会考虑使用TDoubleArrayList
。
当然,您可以使用Collections(例如ArrayList),但是如果要使用2D矩阵,则可以“即时”创建具有不同大小的行。 例如,以下示例创建“三角形”矩阵:
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;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.