在我的数据结构类中,我们研究了 Java ArrayList 类,以及当用户添加更多元素时它如何增长底层数组。这是明白的。但是,当从列表中删除大量元素时,我无法弄清楚此类究竟如何释放内存。查看源码,删除元素的方法有3种:
public E remove(int index) {
RangeCheck(index);
modCount++;
E oldValue = (E) elementData[index];
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
return oldValue;
}
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
}
它们都没有减少数据存储数组。我什至开始质疑内存释放是否曾经发生过,但经验测试表明确实如此。所以必须有一些其他的方式来完成,但是在哪里以及如何?我也检查了父类,但没有成功。
最佳答案
它们不会减少底层数组。它们只是减小尺寸。这样做的原因是,如果你在一个数组中有 1000 个元素并删除 1,为什么要重新分配和复制数组?这是非常浪费的,但收效甚微。
基本上 Java ArrayList
有两个重要的属性,理解它们的不同很重要:
大小:
列表
中理论上有多少元素;和容量:底层数组可以容纳多少元素。
当 ArrayList
扩展时,它的大小会增长大约 50%,即使您只添加一个元素也是如此。这是一个类似的反向原则。基本上可以归结为:重新分配数组和复制值(相对)是昂贵的。如此之多,以至于您想最大程度地减少它的发生。只要名义上的大小是数组大小的大约 2 的工厂,就不值得担心。
关于Java:ArrayList如何管理内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2673398/