将新数组分配给现有数组以在 Java 中"清除"数组是一种不好的做法吗?



所以我目前正在开发一个程序,该程序需要能够处理存储在数组中的大量数据,并且需要一种方法来清除数组中的所有内容。对于下面的示例,在内存方面这样做会是一件坏事吗?我知道垃圾收集器最终会为您清理它,但是是否有理由说明另一种方法(例如 for 循环并将其中的每个值设置为 null(可能比这更好?

Object[] objArray = new Object[n];
/*Do some stuff with objArray*/
objArray = new Object[n]

否则,这样做将允许此操作在 O(1( 时间内运行,而不是需要 O(n( 的 for 循环。

这是不好的做法。

首先,为变量分配一个新数组实际上并没有"清除"任何内容(更多内容见下文(。

这是最佳做法:

objArray = null;

这使得原始数组无法访问,因此它(最终(将被垃圾回收。

它还避免了不必要的内存分配,从而创建了用于替换旧数组的空数组。

但是,这两个选项都不会"清除"原始阵列,这可能会造成安全风险,尽管很小。在垃圾回收之前,如果内存内容被转储等,数组的内容可能是可占卜的。

真正清除数组:

Arrays.fill(objArray, null);

不,这不是坏做法。但是,清空数组的所有索引可能会更快(从技术上讲,这就是所谓的实现细节;但请随意在您的特定系统上对其进行基准测试(,因为不需要分配新内存的额外步骤。但是,建议您不要成为所谓的过早优化的受害者,因为如果您以后发现需要进行大量更改,可能会导致您浪费时间。另外,请注意,由于您将继续使用现有的数组对象,因此引用它的代码的任何其他部分也将看到对它的更改。

从技术上讲,这真的无关紧要。

它更多的是关于可读性和意图的沟通。

你看,现在你努力使你的对象不可变。如果无法更改内容,则可以避免各种多线程问题。因此,更新引用以指向新数组并不完全符合这一点。

另一点值得一提:如果你真的想清除数组(至少对于基元类型(,你最好迭代数组并重置它的所有插槽。(显然对于引用类型的数组来说这是不可能的(

这完全没问题,因为你使用的是"原始"数组,而不是任何集合。您可能会对前一个数组的内存分配感到不安全,但不要担心 GC 会为您清理。但在使用集合 API 时,您宁愿调用:

yourCollection.clear()

ByteBuffer 使用的另一种方法是保留原始数组,保留其内容,并从头开始覆盖。使用数组时,请使用最后一个更新元素的索引以避免数组的其余部分。"清除"数组并没有真正获得任何好处,除非处理数组的任何内容都在寻找一些特定的值来指示内容的结束。

典型的 Java 用户不必担心内存管理,除非安全性或性能是明显的瓶颈。请参阅相关问题。

如果您确实需要一种方法来"擦除"逻辑的数组(即将数组标记为重置(,并且由于您打算稍后重用该数组,则可以

  • 使用布尔值将数组标记为"不可用",直到它再次被填充(如果数组中的对象不消耗太多内存,则更好的解决方案(

  • 从长远来看,用
  • null填充它,而不是为其分配null以避免多个数组分配(特别是如果n很大(:Arrays.fill(objArray, null);.

最新更新