如果我知道我有多少个元素,我已经知道如何创建一个固定数组。例如,对于7个元素,我做了一些类似于int数组[2][4]的事情。
但是,如果我在开始时有0个元素(这意味着数组在开始时是空的),并且希望随着程序的运行增加数组的大小呢?
基本上,如何添加新行或新列?
你考虑过使用列表吗?
使用ArrayList?
数组根据定义是固定长度的。如果需要动态长度,请使用列表。
这就是不可能调整大小的原因。无论您有1或20个维度,数组的每个维度都被分配为某个位置的连续数据行,并且任何此类序列之后的存储空间对于其他变量和要使用的数据都是公平的。例如,ary=new int[4]可以在内存中表示,如下所示:2
由于数组数据之后可能会有其他变量,因此必须分配一个具有所需大小的新数组,并将所有元素从旧数组复制到新数组。一种策略是,每次达到100%的容量时,将分配大小加倍,以获得恒定的摊余时间复杂性。这或多或少是阿拉里斯特所做的,但正如彼得·劳里所指出的,这浪费了大量的空间。
根据需要,另一种选择可能是LinkedList,其中每个数据元素都是单独分配的,并且包含指向下一个/上一个元素的指针。尽管链接列表非常紧凑(没有浪费的空间),并且能够增长到任何大小,但它有两个主要缺点:
无随机访问(只能从一个元素遍历到下一个/上一个元素)。
非常低效的时间——跨越地址空间到达每个下一个元素完全击退了CPU缓存的风。
编辑:再想一想……即使二维链表是可能的,但你需要多个维度的事实可能意味着顺序遍历对你来说还不够。我的错。
虽然Java中的数组存储在连续的内存块中,但对于二维数组来说,这一点是不成立的。二维数组的每个元素都是对一维数组的引用,但每个引用的元素都可以存储在内存的任何位置。例如,请参阅另一个线程中的这个日志。
谢谢你,先生-我向读者们道歉。应该比从C语言中进行假设更清楚。在上面编辑过。
注意,new int[2][4]是int[]的数组;int[][]数组中的int[]数组最初都是相同的长度,但不要求它们保持相同的长度。int[][]数组的任何元素都可以重新分配长度不同的int[],而不会影响其他元素。"行"和"列"的概念是Java阵列不支持的更高级的概念。
如其他答案所示,使用ArrayList不会改变这一点。此外,根据使用ArrayList的方式,由于int值作为Integer对象自动氧化,可能会导致相当大的开销。
如果要保留数据的矩形形状,我建议您定义一个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.
*
* 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;
}
. . .
}
如果我想在数组中,行代表x,列代表y,点A的坐标(x,y)。我正在努力做这样的事情并扩展它(我的英语不好)。我不能使用列表,因为列表是线性的,我需要它看起来像一个表(双数组)。
@我添加了一些示例代码来演示如何在内部使用一维数组。还可以看看另一个问题的答案。
@用户2995645阵列列表是O(1)随机访问。
ArrayList文档和示例。享受!
明确地:
ArrayList list = new ArrayList();
list.add(1); // Add 1 to the list.
如果我想在数组中,行代表x,列代表y,点A的坐标(x,y)。我正在努力做这样的事情并扩展它(我的英语不好)。我不能使用列表,因为列表是线性的,我需要它看起来像一个表(双数组)。
当然,您可以使用集合(例如arraylist),但是如果您想使用二维矩阵,您可以"即时"创建不同大小的行。例如,下面的示例创建"三角形"矩阵:
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;
}
}
可以动态创建Java数组,但不能动态扩展。您可能希望按照其他建议查看向量或数组列表。
然而,请记住,在您的示例中,您已经创建了一个矩阵,这是一个稍微不同的东西。
创建一个更大的新数组,复制现有元素并添加要添加的元素。您可以使用类似arraylist的东西,但这是昂贵的,将使用大约4倍的内存。如果不想自己调整数组的大小,我会考虑使用TDoubleArrayList。
如果Op的问题是在保持矩形结构的同时调整矩阵的大小,那么Trove的原始数组列表并不是一个完整的解决方案。
@泰德霍普是的,你需要一份这些的清单,即Listmatrix