【发布时间】:2015-07-15 20:07:44
【问题描述】:
我正在尝试生成一组应该(至少)为 6x6 的 2D int 数组。每个数组存储 0-6 的值。我尝试使用简单的HashSet<int[][]> 来存储它们(使用 512MB 内存),但很快我就得到了错误
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
只是进入程序的一小段路。
我想到的存储数组的选项:
以
long的形式将它们存储为基数 7。这仅适用于最多 24 (24.3717) 位,因为long不能超过2^63位。将它们存储为
String(例如,{{0, 0, 0, 1}, {3, 6, 2, 0}}将变为"00013620")。这只会占用 4 倍的空间(我认为),因为 char 仍然是 1 个字节。使用
BitSet或BigInteger之类的东西?我不知道每个是什么或它们是如何工作的。
所以我的问题是:存储从 0 到 6 的 6 x 6 数组的最小方法是什么? 上述选项是否有效?更简单的方法?
注意:如果有必要,我可以使用 8GB 内存。
我的代码(如果你必须知道的话,它与国际象棋有关):
n 是数组的大小(宽度和高度),应该可以达到(或超过)6。
public static HashSet<int[][]> getBoards(int[][] data, int zero, int num) {
HashSet<int[][]> ret = new HashSet<int[][]>(0);
if (zero == num) {
ret.add(data);
} else if (zero == 0) {
for (int y = 0; y < n; y++) {
for (int x = 0; x < n; x++) {
for (int i = 1; i < 7; i++) {
int[][] d0 = new int[n][n];
d0[y][x] = i;
ret.addAll(getBoards(d0, 1, num));
}
}
}
} else {
for (int y = 0; y < n; y++) {
for (int x = 0; x < n; x++) {
if (data[y][x] == 0) continue;
HashSet<int[]> moves = getMoves(data[y][x], x, y);
while (moves.iterator().hasNext()) {
int[] m = moves.iterator().next();
for (int i = 0; i < 6; i++) {
int[][] d0 = arrayCopy(data);
d0[m[0]][m[1]] = i;
ret.addAll(getBoards(d0, zero + 1, num));
}
}
}
}
}
return ret;
}
public static HashSet<int[]> getMoves(int piece, int xPos, int yPos) {
HashSet<int[]> ret = new HashSet<int[]>(0);
for (int y = 0; y < n; y++) {
for (int x = 0; x < n; x++) {
if (x == xPos && y == yPos) continue;
switch (piece) {
case 1:
if (y - yPos == 1 && Math.abs(x - xPos) == 1) ret.add(new int[] {y, x});
break;
case 2:
if (Math.abs(y - yPos) + Math.abs(x - xPos) == 3 && x != xPos && y != yPos) ret.add(new int[] {y, x});
break;
case 3:
if (Math.abs(y - yPos) == Math.abs(x - xPos)) ret.add(new int[] {y, x});
break;
case 4:
if (y == yPos || x == xPos) ret.add(new int[] {y, x});
break;
case 5:
if (Math.abs(y - yPos) == Math.abs(x - xPos) || y == yPos || x == xPos) ret.add(new int[] {y, x});
break;
case 6:
if (Math.abs(y - yPos) <= 1 && Math.abs(x - xPos) <= 1) ret.add(new int[] {y, x});
break;
default:
throw new IllegalArgumentException("Unknown Piece Number (" + piece + ")");
}
}
}
return ret;
}
完整的错误:
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at ChessGenerator.arrayCopy(ChessGenerator.java:120)
at ChessGenerator.getBoards(ChessGenerator.java:71)
at ChessGenerator.getBoards(ChessGenerator.java:74)
at ChessGenerator.getBoards(ChessGenerator.java:74)
at ChessGenerator.getBoards(ChessGenerator.java:74)
at ChessGenerator.getBoards(ChessGenerator.java:74)
at ChessGenerator.getBoards(ChessGenerator.java:74)
at ChessGenerator.getBoards(ChessGenerator.java:74)
at ChessGenerator.getBoards(ChessGenerator.java:56)
at ChessGenerator.main(ChessGenerator.java:23)
编辑:正如@Louis 指出的那样,我使用HashSets 导致了上述错误,但是,我仍然内存不足
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at ChessGenerator.arrayCopy(ChessGenerator.java:119)
at ChessGenerator.getBoards(ChessGenerator.java:70)
at ChessGenerator.getBoards(ChessGenerator.java:73)
at ChessGenerator.getBoards(ChessGenerator.java:73)
at ChessGenerator.getBoards(ChessGenerator.java:73)
at ChessGenerator.getBoards(ChessGenerator.java:73)
at ChessGenerator.getBoards(ChessGenerator.java:73)
at ChessGenerator.getBoards(ChessGenerator.java:73)
at ChessGenerator.getBoards(ChessGenerator.java:58)
at ChessGenerator.main(ChessGenerator.java:23)
【问题讨论】:
-
@David 不一定
-
我什至无法想象为什么存储 6x6 的 int 值数组会导致内存不足。你能显示一些代码吗?
-
HashSet<int[][]>我认为您不希望数组的equals()和hashCode()使用HashSet。 java 中的数组正在实现hashCode()和equals()以匹配对象标识。具体来说,两个对象 [1,2,3] 和 [1,2,3] 将不相等,并且(可能)具有不同的 hashCode -
你应该阅读this question。实际上,您似乎并没有完全耗尽内存,因此使对象变小可能无济于事。
-
@David 为什么会这样,我该如何解决?
标签: java arrays memory memory-management out-of-memory