2015-09-26 364 views
2

Set维护唯一记录并在现有元素试图重复时更新现有记录。Java Set - 哪个更快Set.add()或Set.addAll()?

考虑以下两种情况。你认为哪个更快,更有效率呢?

方案1:使用的addAll()

Set<String> uniqueSet = new HashSet<String>(); 
uniqueSet = getSomedata(param1); 
uniqueSet.addAll(getSomedata(param2)); 

这里getSomedata()只是返回的数据的收集,在该方法中没有特别的逻辑。

方案2:使用加()

Set<String> uniqueSet = new HashSet<String>(); 
getSomedata(param1, uniqueSet); 
getSomedata(param2, uniqueSet); 

这里getSomedata()是如下

void getSomedata(String param, Set<String> uniqueSet){ 
    while (someCollection.hasNext()){ 
     uniqueSet.add(someCollection.get()); 
    } 
} 
+1

查看实现,它位于JDK附带的src.zip中。如果你正确地设置你的IDE,你应该可以在那里看到它。 – the8472

+1

首先,第一个片段不应该创建一个无用的空HashSet。其次,你应该争取的不是表现。这两者之间的差异可能是微不足道的。你应该努力的是可读性和可维护性。我期望一个名为getSomedata()的方法返回一些数据。不要拿Set作为参数,填充它,不返回任何内容。如果你想将数据添加到List而不是Set,那会怎么样?或者如果你只是想迭代它呢?第一个更自然,更容易理解和使用。 –

+0

@JBNizet,实际上在我的应用程序中,我正在从服务器上暴露的文件中读取大量数据。文件内的行是唯一的,但可以复制到多个文件中。从所有文件收集数据后,我只需要处理唯一的记录。如你所知,List不会强制唯一性。因此,我正在使用Set。 –

回答

1

addAll超过它给收集基本迭代,并且在每一个方法调用add。这里的OpenJDK8实现它的方式:

public boolean addAll(Collection<? extends E> c) { 
    boolean modified = false; 
    for (E e : c) 
     if (add(e)) 
      modified = true; 
    return modified; 
} 

但作为一般的经验法则,不要尝试,除非你绝对相信你能创造一个更好的去发明轮子。

+0

仅供参考,JDK 7是相同的。 – vikingsteve

+0

据我所知,问题并不是关于addAll()与add(),而是关于每个方法调用创建自己的小集合,然后将它们全部添加到一个独特的大集合,与创建一个独特的集合和有方法将数据添加到此唯一集合。 –

+0

@JBNizet,你的理解是正确的。 –

1

您的问题不完整。让我们用实际的选择来完成它。

首先,具有填充一个提供Set的方法:

void getSomedata(String param, Set<String> uniqueSet) 

其必须使用像

Set<String> uniqueSet = new HashSet<String>(); 
getSomedata(param1, uniqueSet); 
getSomedata(param2, uniqueSet); 

另一种方法是为具有返回一个新Set的方法:

Set<String> getSomedata(String param) 

你可以使用像

Set<String> uniqueSet = getSomedata(param1); 
uniqueSet.addAll(getSomedata(param2)); 
在这种情况下

,被您忽略该方法如何getSomedata将创建并填充Set这样它会返回。显然,除非它创建投影源数据的自定义Set实现,否则它必须创建一个Set并在返回它之前使用元素填充它。

换句话说,在您打算调用它时,如何实现addAll并不重要,该解决方案已经执行了与其他备选方案相同的工作,因为它已经将所有元素添加到了一个Set。因此,即使addAll的某个特定Set实现具有优化,但它的工作增加了已经执行的将所有元素单独添加到Set的工作。


尽管如此,除非出现真正的性能问题,否则不应该担心性能的规则。涉及的I/O可能胜过所有。或者热点优化和内存管理的不可预测性可能会改变这一切。如果你认为,getSomedate返回一个新的Set更清洁(这是合理的),使用它。


作为附录,我简化了一下。 A HashSet仅在理论上是O(1),但在存在散列冲突时将执行不同的操作,并且在使用具有O(log n)时间复杂度的情况下,集合的不同大小会产生影响,因此替代方案以不同的大小,不完全可比较,取决于使用哪个实现和其他周围的上下文。但趋势仍然相同,尤其是在大多数情况下,没有优化的addAll实现(EnumSet可能是唯一的例外)。