繁体   English   中英

使用ArrayList#trimToSize()方法?

[英]Use of ArrayList#trimToSize() method?

最近发布的一个问题中,我遇到了ArrayList#trimToSize() ,它将支持数组的大小减小到当前的集合大小。

引用javadoc

将此ArrayList实例的容量调整为列表的当前大小。 应用程序可以使用此操作来最小化ArrayList实例的存储。

Javadoc说应用程序可以用来减少后备阵列的内存占用。 如果我没有错,这种方法对于小尺寸不会有用,因为一些参考的成本不会那么大。

但是由于arraylist int newCapacity = (oldCapacity * 3)/2 + 1;使用的算法int newCapacity = (oldCapacity * 3)/2 + 1; 在1.6和int newCapacity = oldCapacity + (oldCapacity >> 1); 在1.7中,当添加新元素时,如果oldcapacity很大,那么它将使用上述算法创建一个新的后备数组,如果在动态扩展后只添加一个元素,则可以分配很多不需要的空间。

我的理由是正确的方法背后还是有其他一些应用程序?

是的,支持阵列在满员时增加了约50%。 例如,下面的程序增加了100万个条目,调用trimToSize然后添加一个条目。 添加条目后,背衬阵列的长度为1.2米,修剪后1米,添加一个项目后1.5米。

因此,除非您知道不再添加到列表中, trimToSize调用trimToSize可能会适得其反。

ArrayList<Integer> list = new ArrayList<>();
Field e = list.getClass().getDeclaredField("elementData");
e.setAccessible(true);
for (int i = 0; i < 1_000_000; i++) {
    list.add(i);
}
System.out.println(((Object[]) e.get(list)).length); //1215487
list.trimToSize();
System.out.println(((Object[]) e.get(list)).length); //1000000
list.add(0);
System.out.println(((Object[]) e.get(list)).length); //1500000

另一种情况是我们添加元素然后删除其中的许多元素。 当我们删除元素时,内部aray保持不变。

您的公式导致最差情况下的开销只有50%的空插槽。 请注意, Object最小大小为24个字节,而阵列中的压缩OOP仅为4个字节。 开销相当于

(0.5*4) / (24+4) == 1/14 == 7%

这几乎不值得考虑 - 这是它可以得到最糟糕的 平均而言,它是数组条目中开销的一半,而且对象通常要大得多。

因此,调用trimToSize之后唯一有意义的是在从之前庞大的arraylist中大量删除之后。 换句话说,几乎从不。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM