清除HashSet与创建新HashSet的内存效率

时间:2013-06-17 19:54:17

标签: java collections garbage-collection

好奇心和效率是这个问题的原因。在某些循环运行后我正在创建许多新的HashSet:

HashSet目前在类的顶部声明为:

private Set<String> failedTests;

然后在代码中,我只是在重新运行测试时创建一个新的failedTests HashSet:

failedTests = new HashSet<String>(16384);

我反复这样做,具体取决于测试的大小。我希望垃圾收集器能够最有效地处理旧数据。但是,我知道另一种选择是在最初创建HashSet:

private Set<String> failedTests = new HashSet<String>(16384);

然后每次循环清除HashSet。

failedTests.clear();

我的问题是在开销等方面最有效的方法是什么?我不知道clear()函数在里面做了什么 - 它是做同样的事情,将旧数据发送到垃圾收集器,还是它做了更有效的事情?另外,我给HashSet一个很大的初始容量缓冲,但是如果一个测试需要超过2 ^ 14个元素,那么.clear()函数会将HashSet重新实例化为16384吗?

要添加,我找到了source code to clear() here。所以它至少是最坏情况的O(n)运算。

使用clear函数,我做了一个测试过程,完成时间为565秒。 使用GC处理它,测试在506秒内完成。

但它不是一个完美的基准,因为还有其他外部因素,如与计算机和网络的文件系统连接。但是整整一分钟确实感觉非常好。有没有人推荐一个适用于线/方法级别的特定分析系统? (我正在使用Eclipse Indigo)

2 个答案:

答案 0 :(得分:6)

  

我不知道clear()函数在

中做了什么

它正在调用它在内部使用的clear()表的HashMap方法。在HashMap clear()范围内,public void clear() { modCount++; Entry[] tab = table; for (int i = 0; i < tab.length; i++) tab[i] = null; size = 0; } 方法定义如下:

tab[i] = null
  

它做了同样的事情,将旧数据发送到垃圾箱   收集,还是它做得更有效率?

HashSet指出它使旧数据符合垃圾收集条件。

  

另外,我给HashSet一个很大的初始容量缓冲,但是   如果测试需要超过2 ^ 14个元素,那么.clear()函数   将HashSet重新实例化为16384?

不,不会。

  

这是在开销方面做到这一点的最有效方法,   等?

我想,Java垃圾收集器知道如何以最有效的方式完成工作。所以让垃圾收集器来处理这个问题。所以,我更愿意在每次需要时创建一个新的失败的测试{{1}}。

答案 1 :(得分:4)

重新创建HashSet效率更高。

1)如果HashSet容量增长到16384以上,则不会将其重置为初始容量

2)新的HashSet(16384)创建一个新的Entry [16384]数组,它是一个操作,它比逐个清空元素更有效,如清楚

for (int i = 0; i < table.length; i++)
    tab[i] = null;