Java 从哈希映射中删除未使用的已分配内存

Java 从哈希映射中删除未使用的已分配内存,java,memory,hashmap,garbage,Java,Memory,Hashmap,Garbage,我想读取一些XML文件并将其转换为图形(没有图形,只是一个模型)。但是由于文件非常大(2,2 GB),因此保存所有信息的模型对象变得更大(文件大小的4倍…) 我在网上搜索,试图找到减小对象大小的方法。我尝试了不同的集合类型,但希望坚持使用HashMap(因为我必须具有随机访问权限)。实际的键和值只占分配内存的一小部分。哈希表的大部分是空的 如果我不是完全错的话,垃圾收集不能帮助我释放分配的内存并减小hashmap的大小。是否有其他方法可以释放未使用的内存并收缩hashmap?或者有没有一种方法可

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

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

如果我不是完全错的话,垃圾收集不能帮助我释放分配的内存并减小hashmap的大小。是否有其他方法可以释放未使用的内存并收缩hashmap?或者有没有一种方法可以实现完美的散列?还是我应该用另一个收藏

提前感谢,


Sebastian

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

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

填充贴图后,可以将其复制到另一个大小更合适(更小)的
HashMap
,从而获得更大的填充百分比

您的问题似乎暗示您担心的是,有更多已分配但未使用的对象。但情况如何呢

附录

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


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

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

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

填充贴图后,可以将其复制到另一个大小更合适(更小)的
HashMap
,从而获得更大的填充百分比

您的问题似乎暗示您担心的是,有更多已分配但未使用的对象。但情况如何呢

附录

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


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

您所要求的不是很清楚,不清楚内存是由放置在hasmap中的对象占用还是由hashmap本身占用,这不应该是因为它只保存引用


在任何情况下,请看一看,也许这就是您正在寻找的:它是一个哈希映射,不能保证密钥保存在其中,它应该被用作一种缓存,但从您的描述中,我真的不知道这是否是您的情况。

您的问题不太清楚,不清楚内存是由放置在hasmap中的对象占用还是由hashmap本身占用,这不应该是这样的,因为它只保存引用


在任何情况下,请看一看,也许这就是您正在寻找的:它是一个hashmap,不能保证密钥保存在其中,它应该用作一种缓存,但从您的描述中,我真的不知道这是否是您的情况。

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

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

一个可能起作用的因素是,您可能有引用旧的较大字符串的子字符串,这些子字符串使得GC无法收集太大的字符数组

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

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

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

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

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

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

试着把它们放在一边