0 java collections apache-commons guava
我有一个用例,我需要存储大约大小的键 - 值对。大小为 8 GB 的单个 VM 中的 5 亿个条目。Key 和 Value 属于 Long 类型。键从 1、2、3 开始自动递增,依此类推。
仅当我在程序开始时构建这个 Map[KV] 结构作为独占操作,一旦构建,仅用于查找,在此结构中不会执行更新或删除。
我已经用 java.util.hashMap 尝试过这个,但正如预期的那样,它消耗了大量内存并且程序给 OOM:堆使用超过错误。
我需要一些有关以下方面的指导,这有助于减少内存占用,我对访问性能有所下降感到满意。
只需使用long[]或long[][]。
5 亿个升序键小于 2^31。如果超过 2^31,请使用long[][]第一个维度小而第二个维度大的地方。
(当键类型为整数时,如果键空间稀疏,则只需要复杂的“映射”数据结构。)
一维阵列中的空间浪费是微不足道的。每个 Java 数组节点都有 12 字节的头,节点大小四舍五入为 8 字节的倍数。因此,5 亿个条目long[]将需要接近 5 亿 x 8 字节 == 40 亿字节,这无关紧要。
但是,JVM 通常无法分配占用整个可用堆空间的单个对象。如果虚拟地址空间非常宝贵,建议使用二维数组;例如new long[4][125_000_000]。这会使查找稍微复杂一些,但这样做很可能会减少内存占用。
如果您事先不知道预期的键数,您可以使用数组和ArrayList对象的组合来做同样的事情。但是ArrayList有一个问题,如果你不设置一个(准确的)容量,内存利用率很可能是次优的。如果您ArrayList通过追加来填充 an ,则 的瞬时内存需求append可能是列表当前空间使用量的 3 倍。