Java:ArrayList如何管理内存

cka*_*nik 5 java memory arraylist

在我的Data Structures类中,我们研究了Java ArrayList类,以及当用户添加更多元素时它如何增长底层数组.这是理解的.但是,当从列表中删除大量元素时,我无法弄清楚这个类究竟是如何释放内存的.查看源代码,有三种方法可以删除元素:

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
}
Run Code Online (Sandbox Code Playgroud)

它们都不会减少数据存储阵列.我甚至开始质疑是否会发生内存释放,但经验测试表明它确实存在.所以必须有其他方式,但在哪里以及如何?我检查了父类,但没有成功.

cle*_*tus 10

它们不会减少底层数组.它们只是减小了尺寸.这样做的原因是,如果数组中有1000个元素并删除1,为什么要重新分配和复制数组?很少收获,这是非常浪费的.

基本上Java ArrayList有两个重要的属性,理解它们是不同的很重要:

  • 大小:概念上有多少元素List; 和

  • capacity:底层数组中可以容纳多少个元素.

ArrayList扩展时,即使您只添加一个元素,它也会增加大约50%的大小.这是一个相反的原理.基本上它归结为:重新分配数组并复制值(相对)昂贵.这么多,以至于你想尽量减少它的发生.只要名义尺寸的阵列大小约为2的工厂,就不值得担心.

  • @ cka3o4nik:它只是一个引用数组.其中一百万仍然只占用大约4MB - 并不值得担心这种罕见的情况. (2认同)
  • 迈克尔说,@ cka304nik减少阵列大小并不是一个大问题.如果你想这样做,你可以调用`ArrayList.trimToSize()`. (2认同)