我想阅读一些XML文件并将其转换为图形(没有图形,只是模型)。但由于文件非常大(2,2 GB),我的模型对象(包含所有信息)变得更大(文件大小的4倍......)。
通过网络搜索我试图找到减少对象大小的方法。我尝试了不同的集合类型,但想坚持使用HashMap(因为我必须随机访问)。实际键和值仅占分配的内存量的一小部分。大多数哈希表都是空的......
如果我没有完全错误,垃圾收集无法帮助我释放分配的内存并减少hashmap的大小。有没有其他方法来释放未使用的内存并缩小hashmap?还是有办法做完美的哈希?或者我只是使用另一个系列?
提前致谢,
塞巴斯蒂安
答案 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的更多时间和空间效率替代品。