java中存储2D数组的最小方法

java中存储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位 将它

我正在尝试生成一组2D
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)