【问题标题】:Is it better to create a new HashSet or to reuse after invoking hashSet.clear()调用 hashSet.clear() 后创建一个新的 HashSet 还是重用更好
【发布时间】:2013-08-29 11:28:56
【问题描述】:

我想在 HashSet 中处理一些新数据,而不需要任何旧数据或旧 HashSet 对象。旧的 HashSet 对象不在其他地方引用。

简单地执行hashset = new HashSet<String>() 并让JVM 释放旧的HashSet 对象的内存更好还是我应该调用hashSet.clear() 并重用相同的HashSet?

根据openJDK,hashSet.clear()是:

public void clear() {
    map.clear();
}

和 map.clear() :

public void clear() {
     modCount++;
     Entry[] tab = table;
     for (int i = 0; i < tab.length; i++)
         tab[i] = null;
     size = 0;
 }

由于map.clear()会迭代所有的entry,hashSet很大的时候会不会很耗时?在这种情况下推荐使用哪一个,构造方法还是 clear() 方法?

【问题讨论】:

  • hashSet = null; 怎么样?
  • @AniketThakur 好吧,事实上,我需要一个新的 hashSet。如果我之后要新建一个 hashSet,是否还需要将 hashSet 分配为 null?
  • @wings 否。不要将其设置为 null。如果您需要一个新的 HashSet,请创建一个。或者,可能更好的是使用不同的变量,因为新的 HashSet 可能会用于其他用途。

标签: java memory jvm hashset


【解决方案1】:

简单的不要再引用你的HashSet,让垃圾收集器来做。

在取消引用之前清除 HashSet 不会更快地释放内存。

【讨论】:

    【解决方案2】:

    不需要清除 HashSet - 只需删除对 HashSet 的所有引用(如果您写 hashset = new HashSet&lt;&gt;(); 会发生这种情况,假设旧的 HashSet 没有在其他任何地方引用),然后垃圾收集器将完成剩下的工作。

    还要注意,假设您需要一个相同大小的新 HashSet,calling hashset.clear() takes more time than simply creating a new one with the appropriate capacity

    【讨论】:

    • 那么你释放内存的解决方案是分配更多的内存?这没有任何意义。该对象将在超出范围时清除。您只是用另一张地图替换了一张地图。
    • @EricStein 我认为 OP 需要一个新的 HashSet - 否则确实没有任何意义。我已经澄清了。
    • @assylias 谢谢,这真的很有帮助。你能告诉我,我需要将旧的 hashSet 分配给 null 吗?它是否有助于“通知” GC 释放内存?如果将 hashSet 中的每个条目都分配为 null 没有用,为什么 jdk 本身应该提供一个这样的 clear() 函数而不是简单地新建一个 hashSet?是因为内存容量的原因吗?
    • @wings 如果将null 分配给任何变量,内存将不会被快速释放。如果内存已满,垃圾收集器会释放内存。
    • @wings 您不能替换对象本身。因此集合只能将所有引用设置为null。从外部您可以简单地创建一个新对象。
    【解决方案3】:

    我认为这里有一个误解。您不会手动释放 java 中的内存。即使您调用System.gc();,也不能保证此时会运行 GC。

    至于你的问题:我认为你应该在尽可能小的范围内使用你的引用,当代码离开你的Set 的范围时,对它的引用就会被删除,GC 会收集它。

    clear(); 我认为如果您对Set 有进一步的工作,建议使用:例如,如果您处理了其中的数据并且准备将一些其他数据放入其中。

    在实践中,我几乎从未见过显式的 mySet = null; (如果你想要显式取消引用,你应该使用它,因为 mySet = new HashSet&lt;&gt;() 没有任何意义) 语句,因为它更容易而且更少只使用适当的范围很麻烦。

    【讨论】:

      【解决方案4】:

      在 java 中无法释放内存。你所能做的就是让虚拟机知道它可以在它想要的时候释放它。当事情超出范围时,这通常会发生。一般来说,不用担心也没关系。如果您分析过您的应用并发现内存泄漏,那么您可以尝试找到它。

      绝对不要创建新的 HashSet。 clear() 将从 HashSet 中删除所有项目,但在超出范围之前仍不会被收集。

      【讨论】:

      • 谢谢。但是我不太了解您的“绝对不要制作新的HashSet”。你能进一步解释一下吗?
      • @wings 如果您需要一个新对象,请创建一个新对象。不要只是创建一个来删除对旧的引用。
      【解决方案5】:

      如果您的对象没有任何引用,垃圾收集器会自动删除它们。您无需手动操作。

      【讨论】:

        【解决方案6】:

        这取决于,如果您的地图非常小,那么在这种情况下,清除会比生成对象更好。

        如果你的地图中有很多物品,那么甚至不值得清除它。就像您看到 clear() 方法的实现一样,它会遍历所有元素。在这种情况下,创建新对象会便宜一些。

        但通常最好让垃圾收集器负责清理事物,然后您继续创建新对象,而垃圾收集器将清除剩余的引用。

        但根据经验,应该尝试限制创建的对象数量。 正如我所说,这取决于。

        【讨论】:

          【解决方案7】:

          内存管理由JVM自己完成。因此,即使您手动释放内存,也将自动进行垃圾收集。

          垃圾收集器减少了有关内存管理的编码工作。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-12-19
            • 1970-01-01
            • 2015-02-01
            • 2012-07-15
            • 2014-07-10
            • 2015-07-05
            相关资源
            最近更新 更多