9

好奇心和效率是这个问题的原因。我处于某些循环运行后创建许多新 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?

补充一点,我在这里找到了 clear() 的源代码。所以它至少是最坏情况的 O(n) 操作。

使用清除功能,我做了一个测试过程,在 565 秒内完成。使用 GC 处理,测试在 506 秒内完成。

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

4

2 回答 2

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;
}

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

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

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

不,不会的。

就开销等而言,哪种方法最有效?

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

于 2013-06-17T20:06:29.087 回答
5

重新创建 HashSet 效率更高。

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

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

for (int i = 0; i < table.length; i++)
    tab[i] = null;
于 2013-06-17T20:14:33.247 回答