java中存储2D数组的最小方法
我正在尝试生成一组2Djava中存储2D数组的最小方法,java,arrays,memory,memory-management,out-of-memory,Java,Arrays,Memory,Memory Management,Out Of Memory,我正在尝试生成一组2Dint数组,这些数组(至少)应该是6x6。每个数组存储0-6之间的值。我尝试使用一个简单的哈希集来存储它们(内存512MB),但很快就出现了错误 Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded 只有很短的一段路要走 我想到的存储阵列的选项有: 将它们作为long存储在base 7中。这最多只能用于24(24.3717)位,因为long不能超过2^63位 将它
int
数组,这些数组(至少)应该是6x6。每个数组存储0-6之间的值。我尝试使用一个简单的哈希集来存储它们(内存512MB),但很快就出现了错误
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
只有很短的一段路要走
我想到的存储阵列的选项有:
将它们作为long
存储在base 7中。这最多只能用于24(24.3717)位,因为long
不能超过2^63
位
将它们存储为字符串
(例如{{0,0,0,1},{3,6,2,0}}
将变成“00013620”
)。这只会占用4倍的空间(我想),因为char仍然是1字节
使用类似于位集
或大整数
?我不知道它们是什么,也不知道它们是如何工作的
因此,我的问题是:存储0-6之间的6 x 6值数组的最小方法是什么?以上选项有效吗,还是有更简单的方法
注意:如果有必要,我可以使用8GB的内存
我的代码(如果你必须知道,它与国际象棋有关):
n
是数组的大小(宽度和高度),应该能够达到(或超过)6
EDIT:正如@Louis指出的,我使用的HashSet
s导致了上述错误,但是,我的内存仍然不足
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)
如果您希望HashSet
只保留唯一的int[][]
s并消除重复项,那么这是行不通的--等于并且hashCode
对于int[][]
(以及所有数组)的实现是基于身份的。如果您一直依赖唯一性来保持不同数组的数量较小,那么这是行不通的;您必须将它们封装在一个类型中,实现一个正确的hashCode
和equals
您似乎创建了很多板,这很难理解,但似乎您基本上生成了一大部分大小为6X6的数组,其中每个单元格都可以有1,2,…,6的任意值
此类阵列的数量为6^36~=10^28
这意味着,即使每个数组只有一个字节(不可能),您仍然需要10^16 TB才能容纳所有字节
我建议您寻找一种不包括显式生成所有可能数组的替代方法
顺便说一句,表示对象的最低位数是ceil(log_2(6^36))=94,但要得到这个最佳结果需要做大量的工作,我不建议这样做。最简单但仍然节省内存的方法是将每个数组存储为两个长的,每个字段占用3位(即3*36=总共108个有用位,开销为20个未使用位)。虽然理论上的限制小于此,但您几乎肯定希望您的结构与单词边界对齐,因此您不会真正失去任何东西。不过,您赢得的是,访问单个字段既简单又快速,只需要位屏蔽和移位操作
我还想看看堆外存储选项,以消除所有对象开销。@David Not necessarily我甚至无法想象为什么存储6x6 int值数组会导致内存不足。你能给我看一些代码吗?HashSet
我想你不需要数组的equals()
和hashCode()
的HashSet
。java中的数组正在实现hashCode()
和equals()
以匹配对象标识。具体来说,两个对象[1,2,3]和[1,2,3]将不相等,并且(可能)具有您应该读取的不同hashCode。实际上,您似乎没有完全耗尽内存,因此将对象变小可能没有帮助。@David为什么会发生这种情况,我该如何解决它?但是哈希集或类似类是最小的方法吗?首先,您必须确保您的代码确实在做您想要做的事情,然后您可以担心这一点。现在,我几乎可以肯定它没有做你想做的事HashSet
会给每个元素带来相当大的开销,但是如果需要唯一性,就需要唯一性,如果要保持与int[][]
内容相关的内容的唯一性,就需要一个包装器类型。现在,我更担心的是生成数组列表,而不是让它唯一。在这种情况下,ArrayList
会消耗更少的内存。另外,如果有帮助的话,如果您事先知道行数,一维数组可能比二维数组占用的内存要少得多。谢谢您,我使用了ArrayList
,程序运行得非常好。你能解释一下你的第一个评论吗?我希望它们是独一无二的。它不会(不应该)创建所有板的列表。即使是这样,它是否适用于5x5?4x4?它确实适用于3x3。@ricky3350的要点是-您生成的数组太多了,您需要想出一种方法来查看您想要的数组,而不必显式生成所有数组。
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)
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)