Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 收缩集合的内存开销_Java_Memory_Collections - Fatal编程技术网

Java 收缩集合的内存开销

Java 收缩集合的内存开销,java,memory,collections,Java,Memory,Collections,我最近一直在研究Java集合。我注意到,ArrayList、ArrayDeque或HashMap包含辅助函数,这些函数可以在必要时扩展容器的容量,但它们都没有在容器变空时缩小上限的函数 如果我是对的,那么引用(4字节)的内存成本是否如此无关?你是对的,大多数集合都有一个内部容量,可以自动扩展,而且不会缩小。例外情况是ArrayList,它有方法ensureCapacity()和trimToSize(),允许应用程序显式管理列表的内部容量。在实践中,我相信这些方法很少使用 自动增长但不自动收缩的策

我最近一直在研究Java集合。我注意到,
ArrayList
ArrayDeque
HashMap
包含辅助函数,这些函数可以在必要时扩展容器的容量,但它们都没有在容器变空时缩小上限的函数


如果我是对的,那么引用(4字节)的内存成本是否如此无关?

你是对的,大多数集合都有一个内部容量,可以自动扩展,而且不会缩小。例外情况是
ArrayList
,它有方法
ensureCapacity()
trimToSize()
,允许应用程序显式管理列表的内部容量。在实践中,我相信这些方法很少使用

自动增长但不自动收缩的策略基于对集合使用模型的一些假设:

  • 应用程序通常不知道要存储多少元素,因此集合会随着元素的添加而自动扩展
  • 一旦集合完全填充,元素的数量通常将保持在该数量附近,既不会显著增加也不会显著减少
  • 与元素本身的大小相比,集合的每元素开销通常较小
对于符合这些假设的应用程序,该策略似乎运行良好。例如,假设将一百万个键值对插入到
HashMap
中。默认负载系数为0.75,因此内部表大小为133万。表格大小被四舍五入到二的下一次幂,即
2^21
(2097152)。从某种意义上说,这在地图的内部表中大约有一百万个“额外”插槽。由于每个插槽通常是一个4字节的对象引用,因此浪费了4MB的空间

但请考虑,您使用这个映射来存储一百万个键值对。假设每个键和值都是50字节(看起来像一个非常小的对象)。存储数据需要100MB。相比之下,4MB额外的地图开销并不是什么大不了的事

但是,假设您已经存储了一百万个映射,并且您希望遍历它们并删除除一百个感兴趣的映射之外的所有映射。现在您正在存储10KB的数据,但地图的
2^21
元素表占用了8MB的空间。那是很大的浪费


但似乎从地图上执行999900次删除也是一件不太可能的事情。如果要保留100个映射,可能需要创建一个新映射,只插入要保留的100个映射,然后丢弃原始映射。这将消除空间浪费,而且可能会快得多。有鉴于此,在实践中,缺少集合的自动收缩策略通常不是问题。

差不多。如果一个集合增长太多,需要扩展,它很可能会再次扩展。存储和性能之间的平衡。
ArrayList
具有
trimToSize()
缩小“参考成本”上限是不相关的;只要是这样。要点是:如果您的程序必须对大量数据进行计算;那么它可能不再无关紧要了。示例:当您被要求处理数百万个数字时;那么,选择int数组可能是有意义的;而不是使用整数对象的ArrayList。