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

E.S*_*.S. 9 java collections garbage-collection

好奇心和效率是这个问题的原因.我遇到的情况是,在某些循环运行后我创建了许多新的HashSet:

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

private Set<String> failedTests;
Run Code Online (Sandbox Code Playgroud)

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

failedTests = new HashSet<String>(16384);
Run Code Online (Sandbox Code Playgroud)

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

private Set<String> failedTests = new HashSet<String>(16384);
Run Code Online (Sandbox Code Playgroud)

然后每次通过循环清除HashSet.

failedTests.clear();
Run Code Online (Sandbox Code Playgroud)

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

要添加,我在这里找到了clear()源代码.所以它至少是最坏情况的O(n)运算.

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

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

Vis*_*l K 6

我不知道clear()函数在里面做了什么

它正在调用它在内部使用clear()HashMap表的方法.内HashMapclear()方法被定义如下:

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

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

tab[i] = null 指出它使旧数据符合垃圾收集条件.

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

不,它不会.

在开销等方面,这是最有效的方法吗?

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

  • 大型物体直接进入终身空间,因此GC对它们来说比苗圃一代中GC较小的物体更昂贵.尽管如此,与迭代后备阵列的所有16000个元素的成本相比,这个成本相形见绌. (2认同)

Evg*_*eev 5

重新创建 HashSet 效率更高。

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

2) new HashSet(16384) 创建一个新的 Entry[16384] 数组,它是一个操作,它比像 clear 那样一一清空元素更有效

for (int i = 0; i < table.length; i++)
    tab[i] = null;
Run Code Online (Sandbox Code Playgroud)