从HashMaps中删除未使用的已分配内存

时间:2011-05-10 18:22:31

标签: java memory hashmap garbage

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

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

如果我没有完全错误,垃圾收集无法帮助我释放分配的内存并减少hashmap的大小。有没有其他方法来释放未使用的内存并缩小hashmap?还是有办法做完美的哈希?或者我只是使用另一个系列?

提前致谢,

塞巴斯蒂安

6 个答案:

答案 0 :(得分:1)

HashMap通常只是填充到一定容量百分比的大量引用。如果仅填充了80%的映射,则剩余的20%的阵列单元未被使用(即,为空)。额外的开销实际上只是空(空)单元格。

在32位CPU上,每个阵列单元的大小通常为4个字节(尽管某些JVM实现可能会分配8个字节)。那不是那么多未使用过的空间。

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

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

<强>附录

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

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

答案 1 :(得分:0)

你要问的不是那么清楚,不清楚你放入hasmap或hashmap本身的对象是否占用了内存,但不应该是这种情况,因为它只保存引用。

在任何情况下看一下WeakHashMap,也许这就是你要找的东西:它是一个散列图,它不能保证密钥保存在其中,它应该被用作一种缓存但是从你的描述我不知道你的情况是否属实。

答案 2 :(得分:0)

如果无法减少hashmap的内存占用,则可以始终将数据放入数据库中。根据数据的访问方式,如果在db前面引入缓存,则可能仍然可以获得合理的性能。

答案 3 :(得分:0)

可能发生的一件事是你可能有引用旧的较大字符串的子字符串,然后这些子字符串使得GC无法收集太大的字符串数组。

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

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

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

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

答案 4 :(得分:0)

如果你真的很认真,并且有时间,你可以根据minimal perfect hashing

自行实现Map界面。

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

答案 5 :(得分:0)

你可以给the Trove collections一个机会。他们将其宣传为java.util Collections的更多时间和空间效率替代品。