简体   繁体   English

当从ArrayList中删除元素时,为什么Java中ArrayList的元素缓冲区没有减小?

[英]Why the element buffer of ArrayList in java is not reduced in size when elements are removed from ArrayList?

Supposed we have pushed n elements in an ArrayList in java. 假设我们在Java的ArrayList中推送了n个元素。 If we remove all elements from this list, still the elementData buffer array of ArrayList is of size of order n, it does not shrink in size as elements are removed from it. 如果我们从该列表中删除所有元素,则ArrayListelementData缓冲区数组的大小仍为n阶,由于从中删除元素,它的大小不会缩小。 Won't it be better if the size of array shrinks as elements are removed from ArrayList ? 如果将元素的大小从ArrayList中移除,缩小数组的大小会更好吗?

No, it wouldn't. 不,不会。

Changing the size means actually re-creating the array which is slower than just keeping the potentially unused oversize. 更改大小意味着实际上重新创建数组,这比保持潜在的未使用的超大大小要慢。

And in addition, if you want to add elements back again and the array is already big enough, it is way faster. 另外,如果您想再次添加元素,并且数组已经足够大,则速度会更快。 Array creation and copying is a very performance intense operation. 阵列的创建和复制是非常注重性能的操作。

See 看到

http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html

I found this question (and answer) which explains a lot about it: 我找到了这个问题(和答案),这可以解释很多问题:

Why Array list increase dynamically and not decrease dynamically 为什么数组列表动态增加而不动态减少

Edit 编辑

Referring to 's comment, here a short explanation for the System.arraycopy call in the source code for ArrayList#remove: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/ArrayList.java#ArrayList.remove%28int%29 参考的评论,这里是ArrayList#remove的源代码中对System.arraycopy调用的简短说明: http : //grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6 -b14 / java / util / ArrayList.java#ArrayList.remove%28int%29

public E More ...remove(int index) {
     rangeCheck(index);

     modCount++;
     E oldValue = 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;
 }

Well the arraycopy is basically just shifts everything to the left if the index is not the last element. 好吧,如果索引不是最后一个元素,则arraycopy基本上只是将所有内容向左移动。 It does not re-create the array. 不会重新创建阵列。

Let's take a closer look at the exact call: 让我们仔细看看确切的调用:

System.arraycopy(elementData, index+1, elementData, index,
                              numMoved);

System#arraycopy expects the following parameters: System#arraycopy需要以下参数:

public static void arraycopy(Object src,
             int srcPos,
             Object dest,
             int destPos,
             int length)

Source and desination parameters are the same, the elementData (the actual array in the ArrayList). 源参数和目标参数相同,即elementData(ArrayList中的实际数组)。 srcPos is index+1 so the copying begins one after the specified index with the number of total elements to move as length argument. srcPos是index+1因此复制将在指定索引之后的第一个开始,其中要移动的元素总数作为length参数。 desPos is just the index, so thats where our copy will go and this basically just shifts everything right to the specified element to the left, but does not change the array length. desPos仅仅是指数,因此多数民众赞成在我们的副本将去和这基本上只是转移的一切权利以指定元素的左侧,但改变数组的长度。

Shrinking an array involves allocating a new array and copying all the data over. 缩小数组涉及分配一个新数组并复制所有数据。 It can be a costly process. 这可能是一个昂贵的过程。

Also, you can always call trimToSize() if you wanted to recoup space from a ArrayList that has dramatically shrunk. 另外,如果您想从大幅缩水的ArrayList中回收空间,则可以始终调用trimToSize() Not sure I have ever seen this called... 不知道我曾经看过这个叫...

Performance-wise, it's best if you predefine the size of the ArrayList in the constructor. 从性能角度来看,最好在构造函数中预定义ArrayList的大小。 If the initial size is enough to hold all the items you wish to store in the ArrayList, no resizing is ever required. 如果初始大小足以容纳您希望存储在ArrayList中的所有项目,则无需调整大小。

If you would resize when removing items, you might reach a size lower than the initial size, which would later require further resizing as you add more item, which would slow down inserts to the list. 如果在删除项目时要调整大小,则可能会达到小于初始大小的大小,随后在添加更多项目时需要进一步调整大小,这会减慢插入列表的速度。

Therefore it's best to keep the size of the list equal to the initial size at all times (if possible). 因此,最好始终保持列表的大小等于初始大小(如果可能)。

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

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