1

我想读取一些 XML 文件并将其转换为图形(没有图形,只是一个模型)。但是由于文件非常大(2,2 GB),我保存所有信息的模型对象变得更大(文件大小的 4 倍......)。

通过网络搜索,我试图找到减小对象大小的方法。我尝试了不同的集合类型,但想坚持使用 HashMap(因为我必须随机访问)。实际的键和值只占分配内存的一小部分。大多数哈希表是空的...

如果我没有完全错的话,垃圾收集并不能帮助我释放分配的内存并减少哈希图的大小。是否有其他方法可以释放未使用的内存并缩小哈希图?或者有没有办法进行完美的散列?或者我应该只使用另一个集合?

提前致谢,

塞巴斯蒂安

4

6 回答 6

1

AHashMap通常只是填充到一定容量百分比的大型引用数组。如果只有 80% 的地图被填充,剩余的 20% 的数组单元是未使用的(即,为空)。额外的开销实际上只是空(null)单元格。

在 32 位 CPU 上,每个数组单元的大小通常为 4 个字节(尽管某些 JVM 实现可能会分配 8 个字节)。总体而言,这并没有那么多未使用的空间。

填满地图后,您可以将其复制到另一个HashMap尺寸更合适(更小)的地图,从而提供更大的填充百分比。

您的问题似乎暗示您担心有更多已分配但未使用的对象。但这是怎么回事?

附录

一旦映射几乎被填满(通常超过 95% 左右),就会分配一个更大的数组,将旧数组的内容复制到新数组,然后将较小的数组留作垃圾回收。这显然是一项代价高昂的操作,因此为地图选择一个相当大的初始大小是提高性能的关键。

如果您可以(过度)估计所需的单元格数量,则预分配地图可以减少甚至消除调整大小的操作。

于 2011-05-10T18:27:57.467 回答
0

如果您对此非常认真并且有空闲时间,则可以基于最小完美散列制作自己的 Map 接口实现

如果您的键是字符串,那么这里显然有一张地图可供您使用。我自己没有尝试过,但它吹嘘减少了内存使用量。

于 2011-05-10T18:57:12.717 回答
0

如果您在减少哈希图的内存占用方面无济于事,您总是可以将数据放入数据库中。根据访问数据的方式,如果在 db 前面引入缓存,您仍然可以获得合理的性能。

于 2011-05-10T18:43:37.130 回答
0

可能会起作用的一件事是,您可能有引用旧的较大字符串的子字符串,然后这些子字符串使 GC 无法收集太大的 char 数组。

当您使用一些将属性/值作为子字符串从较大字符串返回的 XML 解析器时,就会发生这种情况。(子字符串只是较大字符串的有限视图)。

尝试通过执行以下操作将您的字符串放入地图中:

map.put(new String(key), new String(value));

请注意,当您填充映射时,GC 可能会做更多的工作,如果您没有那么多引用较大字符串的子字符串,这可能对您没有帮助。

于 2011-05-10T18:52:42.433 回答
0

你问的不是很清楚,不清楚内存是由你放在 hasmap 中的对象还是由 hashmap 本身占用的,因为它只包含引用,所以不应该是这种情况。

无论如何,看看WeakHashMap,也许它就是你要找的东西:它是一个哈希图,不能保证密钥保存在其中,它应该用作一种缓存,但从你的描述来看,我没有t真的知道这是否是您的情况。

于 2011-05-10T18:38:01.033 回答
0

你可以试试 Trove 系列。他们将其宣传为 java.util Collections 的更节省时间和空间的替代品。

于 2011-05-10T20:27:42.337 回答