如何在列表数据结构中编写clear()方法?

Bla*_*Cat 25 java data-structures

我最近阅读了一些框架源代码,并注意到他们编写了类似于列表的数据结构的clear()方法.逐个删除元素.

while (_arr.length > 0 )
{

    remove(_arr[0]);

}       
Run Code Online (Sandbox Code Playgroud)

(也许上面看起来有点令人困惑,但这是因为这种语言本身的数组类型本身就是一个动态数组)或

 for (int i = 0; i < size; i++)
  { elementData[i] = null;}
 size = 0;
Run Code Online (Sandbox Code Playgroud)

但我记得我写过这样的代码.该列表装饰了本机数组类型,我写了这样的clear()方法.

 _arr=new Array();
 _size=0;
Run Code Online (Sandbox Code Playgroud)

直接实例化新的本机数组类型.

并且此代码使用具有垃圾收集的语言编写.所以我认为所有元素最终都会被收集,为什么需要一个循环呢?新的会快吗?

Era*_*ran 20

我想动机是重新使用现有的后备阵列而不是分配一个新阵列.这一点很重要,特别是当后备阵列非常大时(在某些极少数情况下甚至可能意味着在旧的数组被垃圾收集之前无法分配新数组).

分配新数组(以及收集旧数组的垃圾)可能比迭代现有数组并将所有元素的引用设置为更耗时null.

编辑:正如评论中所提到的,设置null基于数组的引用List是不够的.你还必须表明它List是空的.在java.util.ArrayList此通过设置完成size属性0.


Ste*_*n C 7

在某些情况下,清除和重用后备阵列更有效.(显然,你需要一个size字段,清除列表时需要将其设置为零!)

  • 清除可减少清空列表时生成的垃圾.
  • 如果逐步增加列表(即没有capacity提示),清除还会减少重新分配生成的垃圾.

但另一方面,它并不总是一个好主意clear.例如;

  • 如果调用cleara ArrayList,则支持数组的大小将保持与列表已满时的大小相同.如果列表很长,则阵列可能非常大.如果你再也不需要那个列表了,那么大阵列会浪费很多空间.

  • GC ArrayList无论如何都必须检查后备阵列中的每个单元,而不管size字段的当前值.它需要将整个数组复制到"to"空间.

  • 这也意味着您需要分配null给"已清除"的单元格以避免内存泄漏.

  • 如果您不断将"新"对象放入大型"旧"数组中,则可能存在由于世代和/或地点因素导致的次要性能问题.

简而言之,如果阵列支持的列表可能在多个GC周期中存在,那么清除(即清除和重用后备阵列的过程)是一个可疑的命题.